Thursday, June 12, 2014

Visual Studio Add-in creation tips : Cannot see the created add-in under Add-in manager in Visual Studio

Problem :


I made an add-in in visual studio and it is visible in any instance of visual studio under Add-in Manager. but if i want to work with the project having a copy of it to another machine, what should be done to make it visible under the add-in manager.

basically, i want be able to let VS of any of my PCs to detect the add-ins that i have created in it or copied from some other machine.

















Solution : 


You need to register the assembly as add-in for VS using an .AddIn file in some of the well-known locations.

The .AddIn file for add-ins that you create are typically in the folder C:\Users\<user>\Documents\Visual Studio <version>\AddIns.















Inside the .AddIn file there is a <Assembly> tag whose value you need to adjust if needed to point to the assembly path. (Open the AddIn file in a text editor)














Note the highlighted line in the above image. The location that mentioned within the Assembly tag should point to the .dll file of the addIn that you have created. Then the next time you open Visual Studio, your addIn will be visible.
























Hope it was a useful tip to you.

Sunday, June 1, 2014

Visual Studio Add-in creation tips : How to change the default icon of an add-in?

Problem :

When you create an add-in Visual Studio, you will see the default set icon as a smiley. May be your requirement needs some other proper icon to be used. The question is how to change the default add-in icon easily.














Solution :

-Open a solution that was created by using the Add-in project type.
-Open the Connect.cs file and navigate to the below shown line in OnConnection() method.











Note the number "59" in the line where the Command object is initialized. This is considered as the index of the current icon of the add-in. You can change this number to a different standard icon to get a new icon.

It is simple as that. Further more you can refer the below shown list to identify which icon stands for which number you specify.







You can see the complete list from the below reference :



Visual Studio Add-in creation tips : Build Error.Unable to delete dll file



Problem :


I was working on an add-in in visual studio where it gave me the above error from the second time onward while building the add-in project. As I searched about the issue, it seemed some other process is being locking the dll file of my add-in.





I made sure that all other projects which are using the add-in are closed but it didn't fix the issue. I even turned the virus guard off since they too may cause some issues like this.So, I manually went to the bin folder of where the add-in project is created and deleted the dll file. then onward the build was successful. but this is only until I close the add-in project in visual studio. once I restart, make some changes and rebuild, the error pops up again is this a bug or is there a way to fix this issue?

Solution : 

What cause this issue may be your Visual Studio run the add-in when your Visual Studio is started. You can disable Add-ins (e.g. “Tools” | “Add-in Manager”) and run “devenv.exe /safemode”. 

























When I start visual studio the add-in runs automatically.This happens because while creating the add-in using the wizard, I checked 'Microsoft Visual Studio 2010' as an application host and then in the next step i too have checked the option saying that I would like to load the Add-in when the host application starts (see the image below). So, automatically, if another project or a website is running at the moment when I tried to modify the add-in in another instance, the add-in project file is getting locked.  


Monday, April 14, 2014

How to remove custom transport headers in a WSO2 ESB Connector

When u send an HTTP request, as same as you set specific headers for the request, you also will get a set of headers in your response as well no matter the response is successful or an error response.

You may get some custom headers along with the standard HTTP headers. In this post, I will be describing on how you should remove those custom headers if you don't want to send them to your end user.

First off all, you should know what are considered as standard headers. You can have a very useul article and along with the necessary list of headers in the below link.

List of HTTP header fields

The following Screenshot shows you a GET request sent from Postman that's made to Google Calendar REST API. You can see the headers section that there are some headers resulted that are not in the above list of standard HTTP headers.

























You can add the below section as a set of properties in your synapse Sequence to be executed after making the call to the endpoint. So, the custom headers can be removed easily.

<!-- Remove response custom header information --> 
<header name="X-Frame-Options" scope="transport" action="remove" /> 
<header name="X-XSS-Protection" scope="transport" action="remove" /> 
<header name="Alternate-Protocol" scope="transport" action="remove" /> 
<header name="X-Content-Type-Options" scope="transport" action="remove" />

Hope it was useful to you.

How to set HTTP headers in a connector for WSO2 ESB

HTTP header fields are components of the message header of requests and responses in the Hypertext Transfer Protocol (HTTP). They define the operating parameters of an HTTP transaction. Most of the API calls requires to set some headers before making each API calls no matter its GET, POST or any other request type. 

In this post, I am going to focus on the headers that needs to be set for HTTP calls for Google Calendar REST API. 














API:                                   Google Calendar
Reference Link:                    https://developers.google.com/google-apps/calendar/v3/reference/
Headers need to be set :  Authorization , Content-Type

What do those headers mean?

Authorization : Authentication credentials for HTTP authentication
Content-Type: The MIME type of the body of the request

Now, let's see how to set those headers within the synapse template of the connector.It's quiet simple and the below code explain them to you.

<template name="test" xmlns="http://ws.apache.org/ns/synapse">
<!-- Set a parameter to get the access token  -->
<parameter name="accessToken"
description="The access token  of the Google Calendar API" />
<sequence>
<!-- Get the access token from the user  through synapse-->
<property name="uri.var.accessToken" expression="$func:accessToken" />

  <!--Set the access token as the Authorization transport header as below --> 
<property name="Authorization"
expression="fn:concat('Bearer ', get-property('uri.var.accessToken'))"
scope="transport" type="STRING" />

 <!-- Setting the Content-Type transport header as below-->
<property name="Content-Type" value="application/json" scope="transport"
type="STRING" />

<call>
<endpoint>
<!-- you can call the required end point from here  -->
</endpoint>
</call>
</sequence>
</template>

As you see above while setting the Authorization header i have used a concatenation function. That's because the authorization header should be set along with the ''Bearer" field concatenated with the access token. 

That's all about it. You can set any HTTP header by following the similar approach. Hope it was useful to you...

Tuesday, April 8, 2014

Using Script mediators to build a Json payoad with optional parameters in a connector for WSO2 ESB

When making requests to an API, it's very important to identify the parameters that are required (mandatory) and that are optional. It's also essential to know the type of those parameters and the proper way of sending them to the API such as if the api supports REST and we are making a REST/json request, we must ensure that the request that we are sending is a valid json string.

In this post, I wanted to focus bit more on how to handle body parameters that are optional. The concept beind using optional parameters are, it says, a user need not mandatory send those values to call that function but if they wish to set those values as well, then the function should support them. 

As in my other similar posts, let me take a real word example to demonstrate this.

API:                     Google Calendar
Function:             CalendarList: insert
Reference Link: https://developers.google.com/google-apps/calendar/v3/reference/calendarList/insert

The above mentioned request is an HTTP POST request to create a new Calendar List Entry.According to the API documentation, it expects a list of values to be sent through the request body and the request body consists of both required and optional parameters. 

So, these should be handled carefully within the synapse template of the connector. The concept is clear. We are going to set a payload factory to send the request body parameters and the required parameters can be directly hard coded. Also, the optional parameters will be added to the request body checking the condition that the parameter holds a value (it should be not null and not empty to be added to the payload).

The below shown code from the synapse template will clearly explain you how this task is handled.

Note that this function has id as the only request body parameter that is considered to be required and all the rest of the parameters are optional.

The request body parameters should be declared as below;

<!-- Required parameters -->
<parameter name="id" description="Identifier of the calendar." />

<!-- Optional parameters -->
<parameter name="defaultReminders" description="A list of authenticated users for this calendar. Each item has method and minutes." />
<parameter name="foregroundColor" description="The foreground color of the calendar in the format '#ffffff'." />
<parameter name="isHidden" description="Whether the calendar has been hidden from the list." />
<parameter name="notificationSettings" description="The method used to deliver the notification. " />
<parameter name="summaryOverride" description="The summary that the authenticated user has set for this calendar." />

Property mediators should be set to the above parameters to map with the proxy as below within the <sequence>.

<property name="uri.var.defaultReminders" expression="$func:defaultReminders" /> 
<property name="uri.var.foregroundColor" expression="$func:foregroundColor" /> 
<property name="uri.var.isHidden" expression="$func:isHidden" /> 
<property name="uri.var.notificationSettings" expression="$func:notificationSettings" /> 
<property name="uri.var.summaryOverride" expression="$func:summaryOverride" />

Then the payload factory can be added with the required (mandatory) parameters as shown below.

<!-- Building request with mandatory params -->
<payloadFactory media-type="json">
<format>
{
"id":"$1"
}
</format>
<args>
<arg expression="get-property('uri.var.id')" />
</args>
</payloadFactory>

Finally, the script mediator can be used to add the optional request body parameters on checking the conditions as below.

<script language="js">
<![CDATA[        
//request body param variables
var defaultReminders = mc.getProperty('uri.var.defaultReminders');
var foregroundColor = mc.getProperty('uri.var.foregroundColor');
var isHidden = mc.getProperty('uri.var.isHidden');
var notificationSettings = mc.getProperty('uri.var.notificationSettings');
var summaryOverride = mc.getProperty('uri.var.summaryOverride');                                    
//getting the json payload of the message context.
var payload = mc.getPayloadJSON();
//if values set for defaultReminders Array, then add it to the payload
if ( defaultReminders != null && defaultReminders != "") { 
payload.defaultReminders = eval("("+defaultReminders+")");
}
//if a value is set for foregroundColor , then add it to the payload
if (foregroundColor != null && foregroundColor != "") {
payload.foregroundColor = foregroundColor;
}
//if isHidden parameter is set, add it to the payload
if (isHidden != null && isHidden != "") {
payload.hidden = isHidden;
}
//if values set for notificationSettings Object, then add it to the payload
if ( notificationSettings != null && notificationSettings != "") { 
payload.notificationSettings = eval("("+notificationSettings+")");
}
//if values set for summaryOverride , then add it to the payload
if (summaryOverride != null && summaryOverride != "") {
payload.summaryOverride = summaryOverride;
}
//add the payload to the message context
mc.setPayloadJSON(payload);
]]>
</script>

Finally you can use the call mediator by setting required or optional URL parameters to call the function appropriately.

Hope it was useful to you.

How to parse Complex data types or arrays through payload in a synapse template of a connector for WSO2 ESB?

Here I am going to focus on a REST API where we should be able to pass objects or arrays as a rest request in json. Let me start with a real word example as shown below.

API:                     Google Calendar
Function:             CalendarList: insert
Reference Link: https://developers.google.com/google-apps/calendar/v3/reference/calendarList/insert
Sample REST Request:

{
    "id": "836g6ropqm741sqsjl7abcde@group.calendar.google.com",
    "defaultReminders": [
        {
            "method": "email",
            "minutes": 60
        }
    ],
    "notificationSettings": {
        "notifications": [
            {
                "type": "eventCreation",
                "method": "email"
            },
            {
                "type": "eventResponse",
                "method": "email"
            }
        ]
    }
}

Note that the above highlighted values are complex types such as defaultReminders being a list and notificationSettings being an object. The proxy will accept only the first level parameters. So that the objects and arrays will be accepted in the proxy as one single parameter as shown below.

<proxy xmlns="http://ws.apache.org/ns/synapse"
       name="googlecalendar_createCalendarEntry"
       transports="https,http"
       statistics="disable"
       trace="disable"
       startOnLoad="true">
   <target>
      <inSequence>        
         <property name="id" expression="json-eval($.id)"/>       
         <property name="defaultReminders" expression="json-eval($.defaultReminders)"/>
         <property name="notificationSettings" expression="json-eval($.notificationSettings)"/>         
         <googlecalendar.createCalendarEntry>
            <id>{$ctx:id}</id>         
            <defaultReminders>{$ctx:defaultReminders}</defaultReminders>           
            <notificationSettings>{$ctx:notificationSettings}</notificationSettings>           
         </googlecalendar.createCalendarEntry>
         <respond/>
      </inSequence>
      <outSequence>
         <send/>
      </outSequence>
   </target>
   <description/>
</proxy>
              
Now the challenge comes on how we are going to add them to the payload factory inside the synapse template. Of course we have to use a script mediator because the above highlighted parameters are considered as optional parameters according to the API. Unlike handling string values, integers or even booleans, a valid json string does not accept "" surrounded within the values of complex types like arrays and objects but they should be sent within {} or []. 

To achieve the task, we must use eval function in JavaScript.

The eval() function evaluates or executes an argument.If the argument is an expression, eval() evaluates the expression. If the argument is one or more JavaScript statements, eval() executes the statements.
.
Note how it should be handled within a script mediator as shown below.

<script language="js">
        <![CDATA[      
               var defaultReminders = mc.getProperty('uri.var.defaultReminders');   
               var notificationSettings = mc.getProperty('uri.var.notificationSettings');
                            
var payload = mc.getPayloadJSON();
if ( defaultReminders != null && defaultReminders != "") { 
                 // if not null, add optional defaultReminders Array 
payload.defaultReminders = eval("("+defaultReminders+")");
}
if (notificationSettings != null  && notificationSettings != "") { 
                 // if not null , add optional notificationSettings JSON Obj
payload.notificationSettings = eval("("+notificationSettings+")");
}
mc.setPayloadJSON(payload);
]]>
</script>

Hope it was useful to you...