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!