November 18th, 2013

Building Browser Link extension in Visual Studio 2013

Browser Link feature in Visual Studio 2013 provides APIs for you to write your own Browser Link Extension. To take a look at some of the extensions, you can download Web Essentials for Visual Studio 2013 RTM.

In this blog, I will give you a step by step overview of the various APIs that we provide.

You will need the following to start with:

  1. Visual Studio 2013 RTM.
  2. Visual Studio 2013 SDK.
  3. Go to http://sidewaffle.com/ and download a template for extensions.

Once you have installed all of the above, you can get started:

**Step 1: ** Go to  File –>New-> Visual C# –> Extensibility and select Browser Link Extension as shown in the image below.

image

Click OK, to create MyBrowserLinkProject. The browser link project will have a C# file and a JavaScript file. In the sample project, we have MyBrowserLinkProjectExtension.cs file and a MyBrowserLinkProjectExtension.js file.

MyBrowserLinkProjectExtension.js contains the script that will be injected in every browser that is invoked after Visual Studio is launched.

Step 2: Open file MyBrowserLinkProjectExtension.cs.

Here you will find a MyExtensionFactory class that implements interface IBrowserLinkExtensionFactory and MyExtension class that derives from base class BrowserLinkExtension.

MyExtensionFactory class has a CreateExtensionInstance() method and a GetScript().

CreateExtensionInstance method takes in a connection object. A connection can be thought of as a link to a page being rendered. For example, if Visual Studio has IE and Chrome browser rendering a particular page, then each of these can be thought of as a unique connection. You can create a new instance of an extension object or return the same instance of the extension object depending on what you want to do per connection.

 

Code Snippet
  1. public BrowserLinkExtension CreateExtensionInstance(BrowserLinkConnection connection)
  2. {
  3. return new MyExtension();
  4. }

GetScript  method just reads the script to use from MyBrowserLinkProject.js file.

Code Snippet
  1. public string GetScript()
  2. {
  3. using (Stream stream = GetType().Assembly.GetManifestResourceStream(“MyBrowserLinkProject.Scripts.MyBrowserLinkProject.js”))
  4. using (StreamReader reader = new StreamReader(stream))
  5. {
  6. return reader.ReadToEnd();
  7. }
  8. }

 

Step 3: Now, let us look at the MyExtension class itself. This file contains an OnConnected method which you can implement and any number of Browser Link Callback methods.

Code Snippet
  1. public class MyExtension : BrowserLinkExtension
  2. {
  3. public override void OnConnected(BrowserLinkConnection connection)
  4. {
  5. Browsers.Client(connection).Invoke(“greeting”, “Hello from Visual Studio!”);
  6. }
  7.  
  8. [BrowserLinkCallback] // This method can be called from JavaScript
  9. public void SendText(string message)
  10. {
  11. MessageBox.Show(message);
  12. }
  13. }

 

OnConnected() will be called when a connection between Visual studio and browser has happened. This is  a good place to do any kind of initialization. In our example, we have chosen to Invoke the greeting function in Javascript.

Code Snippet
  1. public override void OnConnected(BrowserLinkConnection connection)
  2. {
  3. Browsers.Client(connection).Invoke(“greeting”, “Hello from Visual Studio!”);
  4. }

 

This is how we can make a call from Visual Studio to the browser. In the above example we are trying to call the greetings function in the browser from within visual studio’s extension.

Step 4: Open MyBrowserLinkProjectExtension.js file and you will see the greeting function which you invoked in step 3.

Code Snippet
  1. (function (browserLink, $) {
  2. ///
  3. ///
  4.  
  5. function output(message) { // Helper for the ‘greeting’ function
  6. if (console) {
  7. console.log(message);
  8. }
  9. }
  10.  
  11. return {
  12.  
  13. greeting: function (message) { // Can be called from the server-side extension
  14. output(message);
  15. },
  16.  
  17. onConnected: function () { // Optional. Is called when a connection is established
  18. browserLink.invoke(“SendText”, “Hello from “ + browserLink.initializationData.appName);
  19. }
  20. };
  21. });

Now let us see how we can make a call from Browser to Visual studio. For this, you will need Browser Link Callback methods defined in your extension.

In our example, you can see that we have a “SendText” method with a [BrowserLinkCallback] attribute. This means, this method can be called from javascript running in your browser.

Code Snippet
  1. [BrowserLinkCallback] // This method can be called from JavaScript
  2. public void SendText(string message)
  3. {
  4. MessageBox.Show(message);
  5. }

 

Step 5: Do F5 and this will open up the experimental instance of VS. Here, create a new webforms website. Bring up the Browser Link dashboard. Click on the view in browser link here.

This will bring up a Message box which says “Hello from Internet Explorer”. This way you can see Browser’s JavaScript invoking a Visual studio method.

image

 

Step 6: If you invoke F12 tools in IE, you can see a Browserlink.js file that plugs in the extension script for you in all the browsers.

 

image

 

You can also see that Visual studio has successfully printed in your console. This was done by greetings function in your JavaScript.

Step 1 to 6 was a basic introduction of some of the APIs that you would require to get started.

** Step 7:** Let us look at Actions API.

These APIs provide a way for your Actions(BrowserLinkCallBack Methods) to be invoked via the Browser link Dashboard.

This will give you an entry in the context menu of your connection right next to the Refresh Extension as shown in the image below.

image

 

In our Example, we have two actions defined. One is “Action for SendText” and the other is “Action for Greetings”.

To do this you will need to add the following piece of code:

Code Snippet
  1. public override IEnumerable< BrowserLinkAction> Actions
  2. {
  3. get
  4. {
  5. return new BrowserLinkAction[] {
  6. new BrowserLinkAction(“Action for SendText”, this.AddSendText),
  7. new BrowserLinkAction(“Action for SendGreetings”, this.AddGreetings),
  8. };
  9. }
  10. }

Note that, each of these Action methods AddSendText and AddGreetings inturn invoke a BrowserLinkCallBack method.

Code Snippet
  1. public void AddSendText(BrowserLinkAction action)
  2. {
  3. SendText(“Invoked from Actions context menu!”);
  4. }
  5.  
  6. public void AddGreetings(BrowserLinkAction action)
  7. {
  8. SendGreetings(“Invoked via Actions: Hello from Visual Studio!”);
  9. }

Here are their corresponding BrowserLinkCallBack methods:

Code Snippet
  1. [BrowserLinkCallback] // This method can be called from JavaScript
  2. public void SendText(string message)
  3. {
  4. MessageBox.Show(message);
  5. }
  6.  
  7. [BrowserLinkCallback] // This method can be called from JavaScript
  8. public void SendGreetings(string message)
  9. {
  10. Browsers.Client(_browserlinkConnection).Invoke(“greeting”, message);
  11. }

 

At this point, you can do an F5 on MyBrowserLinkProject. This will open up the experimental instance of VS. Create a Website here and Browse About.aspx with IE and Chrome.

Now click on the little arrow next to chrome and that will bring up the Actions menu for you.

image

Click on Action for SendGreetings and it will print out the following in Chrome’s console as shown in the image below. This lets you test out the BrowserLinkCallback methods quickly on a per connection basis. You can also invoke this on IE and see similar results.

 image

     

Step 8: Mapping Data API.

The API will provide two kinds of operations: mapping a source file position to a DOM element, and mapping a DOM element to a source file range.

All mapping operations will involve a DOM element reference. DOM elements only exist in the browser; they cannot be marshaled to the Visual Studio process. Because of this, the API will only be available in JavaScript. There will be no way to use the API directly from C#.

Each element that can be mapped will have a sourceMapping property attached to it.

Let us see a quick example. Open file MyBrowserLinkProjectExtension.js.

Inside the greeting method, add the following two lines of code. In the example, we are trying to get div1 and open the source file with the complete range for div tag selected.

 

Code Snippet
  1. greeting: function (message) { // Can be called from the server-side extension
  2. output(message);
  3. var testElement = document.getElementById(“div1”);
  4. browserLink.sourceMapping.selectCompleteRange(testElement);
  5. }

Now, do an F5 again. This will bring up experimental instance. Create a Razor website. In About.cshtml file add the following

div tag: 

Select Me

.

View this page in IE Browser. Now from the Dashboard, invoke the “Action for SendGreetings”. This will select the text in source view as shown in the image below.

image

 

You can download WebEssentails2013 and look at  InspectModeBrowserLink.js to see how to make use of the Mapping Data API.

Hope this was useful.

Thanks,

Reshmi

0 comments

Discussion are closed.