Monday 26 September 2011

Change Feature Image in Sandbox Solutions.


So recently, I had created a sandbox solution which deployed a Web Part when the feature associated with my solution was activated. So I thought when the user navigated to the Manage Features page, it should be easier for him/her to recognize which feature has to be activated and decided to assign an custom image to it.

Now my first thought was to deploy an image from the solution and assign its relative URL to the ImageUrl property of the feature. So, I deployed my custom image to the path /myFolder/awesome_img.png and assigned the same relative URL to my feature’s ImageUrl property.

And when I navigated to the Manage Features page, I was greeted with the following:


It turned out that SharePoint by default looks for the assigned image in the /_layouts/images/ folder. So whichever URL I provided to the ImageUrl property, SharePoint appended the /_layouts/images in front of it and assigned it to my feature.

Now since we are in the Sandbox, we do not have access to the _layouts folder. So we cannot deploy our custom Image to the folder and assign it to the feature.

But there is a workaround...and JavaScript has the answer!

So what I did was:
1) Deployed my custom Image to one of my SharePoint libraries.

2) Assigned place holder text to the ImageUrl property of the feature.


3) Wrote this little jQuery script which checked for the place holder text and replaced it with the path to my custom image.


jQuery(document).ready(function () {

      //Check if the current page is the Manage Features page.
     if (location.href.indexOf("ManageFeatures.aspx") != -1) {
           
          //Fetch each image with the place holder as the src.
         jQuery("img[src*='myFeatureImagePlaceHolder']").each(function () {
           
            //Replace the src of the image.
            this.src = this.src.replace("/_layouts/images/myFeatureImagePlaceHolder", _spPageContextInfo.siteServerRelativeUrl + "/myFolder/awesome_img.png");
          
        });
    }
});


4) Using Script delegates, Embedded the jQuery library and my custom JavaScript file into the masterpage, So that they will be available on the Manage Features page.


xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">

<CustomAction Location="ScriptLink" ScriptSrc="~SiteCollection/Scripts/jquery-1.6.min.js" Sequence="1004" />

<CustomAction Location="ScriptLink" ScriptSrc="~SiteCollection/Scripts/ReplaceFeatureIcon.js" Sequence="1005"/>
<Elements>


After deploying the solution, I navigated to the Manage Features page and Voila! The feature image had changed:

Sunday 25 September 2011

View & Edit InfoPath Forms in the SharePoint 2010 Modal Dialog

Recently, there was a requirement in my project that, an InfoPath form (which was stored in a Forms Library on SharePoint) had to be displayed as a pop-up when the user clicked on a particular HTML page element. The user also had to have the functionality to save the changes he/she made to the displyed form.

So naturally, my first thought was to use the JavaScript Modal Dialog which SharePoint provides out of the box. Now, My challenge was to provide it with a relevant URL which pointed to my desired InfoPath form.

I navigated to my InfoPath form stored in the Forms Library and observed the URL which showed in the browser. It was similar to the following:

 [SiteCollection]/_layouts/FormServer.aspx?XmlLocation=[RelativeURLofFormXML]&Source=[FormsLibraryAbsolutePath]&DefaultItemOpen=1

Where:
SiteCollection: URL of the Site Collection
RelativeURLofFormXML: relative path of the XML file of the InfoPath form I wanted to display.
FormsLibraryAbsolutePath: The absolute path of the Forms Library which contained my InfoPath form.


Now, the only thing remaining to do was to take the JavaScript modal dialog and push the form url into it, which i did with the following code:


After that, I assigned the OpenForm( ) function to an anchor tag and when i clicked on it:


I was even able to save the form after filling it! :)

Friday 26 August 2011

JavaScript "L_Menu_BaseUrl" variable for SharePoint

When working with Sandbox Solutions, there are a lot of times when you have to determine the URL or the serverRelativeUrl of the current site. This is especially needed on Office 365.
With the ECMAScript Client Object Model, there are multiple ways to access the current site URL or the serverRelativeUrl like the SP.Site.get_url() for the Root site URL or SP.Web.get_serverRelativeUrl() for the relative url of the current site.

But there is an easier way get the URL  by using the OOB Javascript variable L_Menu_BaseUrl which stores the URL of the current Web or the Subsite.

For example, this was extremely helpful to me for calling the EditDialog on any list item. It worked great with Office 365 top level sites as well as sub-sites:

function OpenEditDialog(itemid)
{
   var options = {

    url: L_Menu_BaseUrl + "/Lists/Claims/EditForm.aspx?ID=" + itemid + "&IsDlg=1",
     width: 700,
     height: 700,
     dialogReturnValueCallback: DialogCallback 
};
     SP.UI.ModalDialog.showModalDialog(options);
}

Here are some more OOB Javascript variables which can be useful: 

L_Menu_LCID : This contains the LCID setting of the current site.
L_Menu_SiteTheme : This contains the theme name of the current site.
_spUserId : This contains the id of the current user.

Tuesday 19 July 2011

Bing Maps Silverlight Control in Office 365

Recently, I was working on Geocoding with the Bing Maps Silverlight Control for a SharePoint 2010 Sandbox application. Everything was going awesome on my on-premise SharePoint 2010 environment but when I uploaded the application in Office 365, every time the application would load I would get a pop-up in IE asking whether to "Display Mixed Content?"

I googled for a solution and manged to learn that since the Office 365 environment was HTTPS and the Bing Maps GeoCoding web service was HTTP, I was being presented with this dialog box asking permission to display both HTTP and HTTPS content. This was also the reason why I was not getting the same pop-up on my on-premise SharePoint 2010 environment as it was also HTTP.

So the solution to this problem I thought was to find an HTTPS version of the Bing Maps GeoCoding web service so I made the following changes in my ServiceReferences.ClientConfig file:

1)Changed the URL of the web service to HTTPS
2)Changed the security mode of the basicHttpBinding from 'none' to 'Transport'

And voila! The annoying pop-up disappeared!

My final Service ServiceReferences.ClientConfig file looked like this:

<configuration>
    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="BasicHttpBinding_IGeocodeService" maxBufferSize="2147483647"
                    maxReceivedMessageSize="2147483647">
                    <security mode="Transport" />
                binding>
            basicHttpBinding>
            <customBinding>
                <binding name="CustomBinding_IGeocodeService">
                    <binaryMessageEncoding />
                    <httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
                binding>
            customBinding>
        bindings>
        <client>
            <endpoint address="https://dev.virtualearth.net/webservices/v1/geocodeservice/GeocodeService.svc"
                binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IGeocodeService"
                contract="GeocodeService.IGeocodeService" name="BasicHttpBinding_IGeocodeService" />
            <endpoint address="http://dev.virtualearth.net/webservices/v1/geocodeservice/GeocodeService.svc/binaryHttp"
                binding="customBinding" bindingConfiguration="CustomBinding_IGeocodeService"
                contract="GeocodeService.IGeocodeService" name="CustomBinding_IGeocodeService" />
        client>
    system.serviceModel>
configuration>

Saturday 11 June 2011

Automatically let VS step through code : The [DebuggerStepThrough] attribute.


This has happened to me numerous times that while debugging, I press F11 (instead of F10) and accidentally step into a generic method or a property which will not provide me with any information which will help in debugging the code.
For example if there is the following property,
 private bool isincorporated;
        public bool IsIncorporated
        {
            get { return isincorporated; }
            set { isincorporated = value; }
        }
And during debugging, a line is encountered such as:

bool CompanyIncorporated = objCompany.IsIncorporated;

The debugger will enter the property, step through the relevant line and return to the calling function. This activity will seldom provide any information which will help in debugging.

To prevent this, there is nifty little attribute called

[System.Diagnostics.DebuggerStepThrough]

Just add this attribute to your method or property and Visual Studio will automatically step over it.

I had huge help from this attribute while working with Silverlight Validations. I had bound a Silverlight TextBox with a property and I had it throw a Custom Exception when that particular property (TextBox) was blank. So essentially my XAML looked like:

<TextBox Name="txtCompanyName" Text="{BindingCompanyName, Mode=TwoWay, ValidatesOnExceptions=True}"/>

And the CompanyName property was implemented in the following way:

 private string companyname;
        public string CompanyName
        {
            get { return companyname; }
            set
            {
                if (value != "")
                {
                    companyname = value;
                }
                else
                {
                    throw new Exception("Company Name cannot be blank.");
                }
            }
        }
So whenever the TextBox was blank, Visual studio would throw an exception and I would find it very difficult to debug further. So what I did was, I added the
[System.Diagnostics.DebuggerStepThrough] attribute to the set method of the property and Visual Studio stopped throwing the exception explicitly.

So my Final code looked like this:

 private string companyname;
        public string CompanyName
        {
            get { return companyname; }
           
     [System.Diagnostics.DebuggerStepThrough]
     set
            {
                if (value != "")
                {
                    companyname = value;
                }
                else
                {
                    throw new Exception("Company Name cannot be blank.");
                }
            }
        }

And now I could debug away happily!

Thursday 26 May 2011

Office 365 and Sandboxed Solutions:Exceeded the daily resource usage quota.

"The site collection containing this sandboxed solution has exceeded its daily resource usage quota."

While working with Sandboxed Solutions on Office 365, you might get this error when you try to activate your solution. I faced this error on the Small business version of Office 365 but it has been know to occur on the Enterprise version too.
There is a limited resource usage quota alloted to each SharePoint Online sitecollection. When this usage quota is exceeded (when you try to activate your solution) , this error occurs.
So far, I have found how to resolve this issue on the Enterprise Version of Office 365 only. I am afraid there is no setting on the Small Business Version (The P1 plan) to manage the allocated resources.
The solution for this issue (on the Enterprise Version) is pretty straightforward:

Go to:
Admin ->
SharePoint Online ->
Manage ->
Manage Sitecollections->
Select your Sitecollection ->
Select Resource Usage Quota -> (on the top of the page)
Enter the new value in MB of your Usage Quota in the resources textbox->
Click Save.

Done. That's all there is to it :)
Enjoy Office 365!

Sunday 15 May 2011

Add Web Part to Page using SharePoint Client Object Model:File not Found error.

When adding a web part to your page if you get the "file not found" error there is one small trick which you probably have to do.

You will most probably get this error if the page you are adding the web part to, is not in the root site of the site collection.

Here is the code to add a web part to your SharePoint page:

ClientContext clientcontext = new ClientContext("http://vardhaman/Sites/zevenseas/");
Microsoft.SharePoint.Client.File page = clientcontext.Web.GetFileByServerRelativeUrl("/Sites/zevenseas/SitePages/Home.aspx");
LimitedWebPartManager wpm = page.GetLimitedWebPartManager(PersonalizationScope.Shared);
string webpartxml = /*The webpart XML */;
WebPartDefinition wpd = wpm.ImportWebPart(webpartxml);
wpm.AddWebPart(wpd.WebPart, "Left", 1);
clientcontext.ExecuteQuery();

Notice that I have passed the entire url of the site when creating the ClientContext object. And also when I have to fetch the page to which the webpart should be added, I have passed the entire site relative url which includes the name of the site which I initially passed to the ClientContext Object.

I was stuck on this error for sometime because I tought that once I had passed the site URL ("http://vardhaman/Sites/zevenseas/") to the ClientContext object, I need to only pass the location of the page within the site ("/SitePages/Home.aspx") when fetching the page. But that did not turn out to be the case.

Have Fun Coding!

Wednesday 27 April 2011

Get HTML from page using the Client Object Model in SharePoint

Here is how to get the RAW HTML of a Web Page on your SharePoint Site using the Client Object Model:

Just substitute your Site Collection name instead of "sitecollection" and your page path along with the Relative Server URL instead of /Sites/Vard/SitePages/Home.aspx



The string variable pageHTML will now have the raw html of the Home.aspx page.

Have Fun!

Monday 25 April 2011

Office365 beta and the SharePoint 2010 Client Object Model

UPDATE: Microsoft has published the article on Authentication the Client Object Model on Office 365. You can find it here:
http://blogs.msdn.com/b/cjohnson/archive/2011/05/03/authentication-with-sharepoint-online-and-the-client-side-object-model.aspx
                                                         -------XXX-------

​I just got my Office365 beta license and configured a new Team Site in Sharepoint Online. Then I thought of accessing this new team site through the SharePoint 2010 .NET Client Object Model when I got the 403: Forbidden error code.

First, I thought that there might be some authenticaion issue so I tried accessing with both Classic Authentication and Claims based authentication.

Forms Based Authentication(Client Object Model):


clientcontext.AuthenticationMode = ClientAuthenticationMode.FormsAuthentication;

clientcontext.FormsAuthenticationLoginInfo = new FormsAuthenticationLoginInfo("username", "password");

Web Service Login:

AuthService.Authentication auth = new AuthService.Authentication();
auth.Url = "http://.sharepoint.com/TeamSite/_vti_bin/authentication.asmx";
auth.CookieContainer = new System.Net.CookieContainer();
AuthService.LoginResult loginresult = auth.Login("username","password");

With both the cases, it gave me the following error:

"Server was unable to process request. ---> The server was unable to process the request due to an internal error."

lists.asmx:

I tried accessing the lists of Office365 through the Lists service:

ListService.Lists list = new ListService.Lists();

list.Credentials = new NetworkCredential("username", "password");

var res = list.GetList("Documents");

but got this clear cut error:

"Server was unable to process request. ---> Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))"


After some digging aroung, I found out that indeed right now, support is not there for the client object model and the only way to currently use the Client Object Model with SharePoint Online is to get the FedAuth Cookie (from fiddler) and then include that cookie in your call from the code. But this is not the best practice and is highly discouraged.

Hopefully, the Office 365 team will include the Client Object Model as soon as possible. I will update it here as soon as there is any news regarding the issue.

Friday 22 April 2011

How to Integrate Facebook with Windows Application


Ever wondered how to integrate Facebook into your application? Just how cool would it be to have Facebook button on your application? Lets do it then...

We will be using an awesome C# Facebook API  called facebooksdk which will make our task extremely easy.

First, In order to use your application to post on Facebook, you need to register your application and get the App ID. The registration is absolutely free. This App ID will help Facebook recognize (and authorize) your application each time a communication is made from the application to Facebook.

To Register your application with Facebook, go to http://www.facebook.com/developers/ and click on "Set Up New App"

Next, we need to give a name to our application, Lets name it DemoApp. Select the Agree button and click on "Create App".



Interesting fact: If the name of your application contains the word "face", Facebook will show you this little number:

When your Application is created, you will be presented with the following screen:
Select various details about you application such as description, Icon , logo, administrator email etc. Then click on "Save Changes".

Now we have come to the most Important screen from our point of view: The MyApps Page where you will be provided with the App Id and other important IDs for your application. You will only require the App Id to successfully authenticate your windows application with Facebook.


Now that you we have our App Id, we need to create a windows application from which we will share our link on Facebook. We will be using the C#, .NET framework 4 and Visual Studio 2010 for our Application. Create a new Windows Application Project in C# and name it something Relevant. Lets name our project as "FacebookDemo"


Once the Windows application is created, Drag a WebBrowser Control and a Button Control on to the Form. These will be the only two controls we will be using in our application.



Next, we need to reference a couple of DLLs which we will be using in our project. Make sure you have the Facebook.dll  and System.Web Assembly referenced in your project.



OK. Enough of screenshots. Time to do some actual coding!



The Facebook SDK provides us with a variety of inbuilt functions. The actual code won't be difficult at all and it will be extremely easy to understand.
The first step we will do is creating a login URL which will help us authenticate our application with Facebook. The following code snippets will create a login URL for us:
(In the Demo Application, I have written this code on the Button Click event of the Button on our Windows Form)

First, we need to create an Instance of the FacebookOAuthClient. The parameters we will be passing will be your App ID which you got when you registered for Facebook and the Redirect Uri which is the Uri to which our Browser will get redirected to when we are successfully authenticated with Facebook.
 The default Uri is http://www.facebook.com/connect/login_success.html but we will override it with http://www.facebook.com/ so that you are redirected to your Facebook homepage when the wall post is made.

var oauth = new FacebookOAuthClient
                   {
                       ClientId = "",
                       RedirectUri = new Uri("http://www.facebook.com/")

                   };

Next, we will create a Dictionary object which will determine the Display type and the Respose type which will be returned.
Display type is the method by which the Authentication dialog will be rendered. It is set to “page” by default. We will override it to popup so that it consumes less space.
You can find the various display options here:

The response type is the result given by Facebook on successful authentication.




                var parameters = new Dictionary<string, object>
                                {
                                    { "display", "popup" },
                                    { "response_type", "token" }
                                };

Next, we define the permissions which our application will have to access the user’s data. Right now, since we only need to share a link on the wall of the user, we will require only one permission from the user which is the “publish stream” permission. With this permission, our application can post on the wall of the user. The complete list of allowed permissions is available here:

                var extendedPermissions = "publish_stream";

                if (!string.IsNullOrEmpty(extendedPermissions))
                {
                    parameters["scope"] = extendedPermissions;
                }

Finally, we will pass the parameters to the GetLoginUrl function of the FacebookOAuthClient class which will return the login uri.


                var loginUri = oauth.GetLoginUrl(parameters);

                                               
We will navigate to the generated loginUri with the webbrowser control which we created on our windows form.
webBrowser1.Navigate(loginUri);


The next step we are going to take is that we are going to check if our login uri is authenticated. We are going to do this by checking the authentication status each time the page changes. The Navigated event of the webbrowser control will be extremely helpful here as it is triggered each time there is a page change.
(In the Demo Application, I have written the following code in the webBrowser1_Navigated event of the webbrowser control so it will get called and check if authenticated each time there is a page change)

First we need to create an instance of the FacebookOAuthResult class which is designed to check and return the result of the authentication request sent to Facebook. TryParse returns true if it is recognized as a OAuth2 Authentication result. There is a property of the FacebookOAuthResult called IsSuccess which is set to true if the OAuth result was successful and we have the access token. You can use the ErrorDescription property to show the user why the error occurred in the authentication.

FacebookOAuthResult authResult;

if (FacebookOAuthResult.TryParse(e.Url, out authResult))
{
       if (authResult.IsSuccess)
       {
            //Code to post an update to the wall of the user. (Code is given in the next part)
                    
       }
       else
       {
            System.Windows.Forms.MessageBox.Show(authResult.ErrorDescription);
       }
}

Next, when we are successfully authenticated by Facebook, we will get an access token which can be used to make the wall post.

         var accessToken = authResult.AccessToken;


The FacebookClient Class is used to get and post updates once we are successfully authenticated. So we will create an object of that class with help of the accessToken which we got from the successful authentication earlier.

            FacebookClient fbc = new FacebookClient(accessToken);


            string encodeaccesstoken = HttpUtility.UrlEncode(accessToken);

            var me = fbc.Get(encodeaccesstoken);


Next, we need to create post. This post can be created the same way as you did earlier by creating a Dictionary object and then adding the different parameters to it. The entire list of parameters you can add to your post can be found here:

            var post = new Dictionary<string, object>
            {
                     { "display", "popup" },
                     { "response_type", "token" }
            };
            post.Add("link", "http://vrdmn.blogspot.com");
            post.Add("message", "The Message You want to Post on Facebook");

I have only added the link (which points to this blog) and the sample message parameters. You can add whichever ones you want.

And the last step is to publish the actual post on Facebook with the Post method of the FacebookClient Class. The parameters passed are the “me/feed” which tells the API where to publish the post and the actual post dictionary object which contains the details about the post.

           fbc.Post("me/feed", post);

You can download the Sample project from here. Be sure to have Visual Studio 2010 Installed.