Wednesday, October 3, 2012

SharePoint server is not installed on this computer

Share/Save/Bookmark

Are you victim of this error? then, you must be trying to use SharePoint 2010 templates in visual studio 2010  on the system that does not have Sharepoint installed.

So how to make it work with out installing the SharePoint server on local machine? After googling around, the hack that i found is to export the registry from SharePoint 2010 machine and import it to the machine where you are running visual studio.
Follow the below detailed steps,


  • Run regedit in command prompt on Sharepoint server
  • Navigate to the path [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\14.0]
  • Copy the whole 14 hive registry by exporting it.(File->Export)
  • Open the registry in local machine where you are trying to develop sharepoint solutions using VS2010
  • Export the copied registry (File->Import)
The last step is to copy the SharePoint dlls at C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\ISAPI from sharepoint server to local machine.
Copy the necessary sharepoint dlls to GAC or use Gacutil to do.
Now after restarting VS you must be able to create projects using sharepoint templates. 
This way i could successfully develop sharepoint solution using  VS2010 when sharepoint is on a different system(in  my case sharepoint online) though debugging is not possible.

Subscribe

Tuesday, September 25, 2012

Query XML using LINQ

Share/Save/Bookmark


I have a scenario, to calculate the size of the documents in library.
Now after i read the library using web service in to xml (soap) i do not want to iterate or loop
all items to read the value in the column,file size. I was wondering if i can apply a aggregate function(sum)
like we have in SQL. Here is how i did with XDocument by applying LINQ on XML

XDocument xDoc = XDocument.Load("test.xml");
// Incase if source is a XmlNode
//Xdocument.Parse(XmlNode.OuterXml);
//namespace is always necesary for xdoc to identify the elements
XNamespace z = "#RowsetSchema";
var size = (from item in xDoc.Descendants(z + "row")
             select Convert.ToDouble(item.Attribute("ows_File_x0020_Size").Value.Substring(item.Attribute("ows_File_x0020_Size").Value.IndexOf('#') + 1))).Sum();

XDocument.Descendants("z:row") will always throw exception that semicolon is not allowed.
Thats one more reason why namespace should be passed.



Subscribe

Sunday, September 9, 2012

component version is not compatible with the search database

Share/Save/Bookmark

One of the reason for causing the below error is due to missing database upgrade in the server for search service application.

ERROR :The synchronization operation of the search component: 8bce98fb-8409-491d-877e-143590c9f055 associated to the search application: Search Service Application on server: has failed. The component version is not compatible with the search database: Search_Service_Application_CrawlStoreDB_4925b8b4b5574940ba8389bffd59423f on server: . The possible cause for this failure is The database schema version is less than the minimum backwards compatibility schema version that is supported for this component. To resolve this problem upgrade this database..


In order to update the SharePoint databases, you must manually run the PSconfig utility. To run the utility:
Check if the server needs update with the following command in the sharepoint powershell admin,

(get-spserver $env:computername).NeedsUpgrade

If it returns TRUE, then follow the steps below

1.Open an Administrative command prompt.

2.Change directory to C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\BIN

3.Run PSConfig.exe -cmd upgrade -inplace b2b -force -cmd applicationcontent -install -cmd installfeatures

This will take couple of minutes to finish.


Subscribe

Saturday, August 18, 2012

Dispose RootWeb,ParentWeb,limitedwebpartmanger?

Share/Save/Bookmark

we all know that disposing SPSite/SPWeb objects is the best practice that will avoid any memory leaks. If you know the first point then you should also know when to dipose?

Objects accessed from the SPContext or properties(feature) do not need to be explicitly disposed but where as instantiated as below need to be.

SPSite site = new SPSite("http://abc.com");

So just wrap the above line of code with using that will automatically dispose the SPSite object when its out of scope.

Using(SPSite site = new SPSite("http://abc.com"))
{
      .....
}

There are some very special cases where we get confused, which I gonna cover here,

SPWeb web = site.RootWeb/ParentWeb
                        or
SPWeb web = SPcontext.Current.Site.RootWeb/ParentWeb

Should the web object be disposed in the above scenario?Certainly NOT, as these objects are disposed implicitly when site object is disposed i.e wrapped "using" when it is instantiated and in other case by sharepoint  when it(spsite) is from SPContext.


That being said how about SPWeb from SPContext.Current.Site.OpenWeb() ?
From the reflector it can be seen that a new instance of SPWeb is created when OpenWeb is called, irrespective of the way SPSite is instantiated.So in the code SPWeb should be disposed always explicitly.

Also, SPLimitedWebPartManager implements IDisposable which means it should be disposed when ever used.
we always follow the below practice when it comes to SPLimitedWebPartManager


using (SPWeb web = site.OpenWeb()) 
{
using (SPLimitedWebPartManager webPartManager = web.GetLimitedWebPartManager(url, scope))
            {
                
                    webPartManager.AddWebPart(mstrReport, entry.Key.ToString(), 0);
                     webPartManager.SaveChanges(mstrReport);
                
            }
}


I had a doubt if SPlimiedWebPartManager should be disposed when it is read from SPContext as below,

SPContext.Current.Web.GetLimitedWebPartManger(..)

So quickly i opened the reflector to see what is happening in the background, then i realized that it should be disposed and along with it the property, web.
Here is the snippet from reflector.


internal SPLimitedWebPartManager GetLimitedWebPartManagerInternal(Uri pageUrl, int pageVersion, PageView requestedView, bool forRender, bool includeHidden)
{
    if (null == pageUrl)
    {
        throw new ArgumentNullException("pageUrl");
    }
    if (!pageUrl.IsAbsoluteUri)
    {
        throw new ArgumentException(WebPartPageResource.GetString("AbsoluteUriRequired"), "pageUrl");
    }
    this.EnsureAspx(this.GetWebRelativeUrlFromUrl(pageUrl.ToString(), false, true));
    SPWeb web = this.Site.OpenWeb(); // THIS  WEB IS NEVER DISPOSED HERE
    web.IsOwnedByWebPartManager = true;
    SPWebPartManager manager = null;
    try
    {
        long num;
        if (this.AllowUnsafeUpdates)
        {
            web.AllowUnsafeUpdates = this.AllowUnsafeUpdates;
        }
        manager = web.GetWebPartManagerInternal(pageUrl, pageVersion, requestedView, forRender, includeHidden, out num);
    }
    catch
    {
        web.Dispose();
        throw;
    }
    if (manager != null)
    {
        return manager.LimitedWebPartManager;
    }
    return null;
}


The above web instance created by sharepoint in the method is not disposed. So i checked if it is doing it in SPLimitedWebPartManager.Dipose()



public void Dispose()
{
    if (!this.m_disposed)
    {
        if (this.m_manager != null)
        {
            this.m_manager.Dispose();
        }
        this.m_webParts = null;
        this.m_webPartDefs = null;
        this.m_manager = null;
        this.m_disposed = true;
    }
}


Ah, Its not doing even here which clearly shows that it should be explicitly disposed by the developers.
So best practice gonna be as below.


using (SPWeb web = site.OpenWeb()) // SPWeb web = SPContext.Current.Web
{
using (SPLimitedWebPartManager webPartManager = web.GetLimitedWebPartManager(url, scope))
            {
                 try 
                   {
                    webPartManager.AddWebPart(mstrReport, entry.Key.ToString(), 0);
                     webPartManager.SaveChanges(mstrReport);
                   }
                finally
                  {
                   // this web is created by sharepoint but not the above one
                      webPartManager.Web.Dispose(). 
                  }
                
            }
}




 Subscribe

Wednesday, August 15, 2012

component version is not compatible with search database

Share/Save/Bookmark

Search service application may not work in your sharepoint environment due to missing database upgrade throwing the below error.

Error:
The synchronization operation of the search component: 8bce98fb-8409-491d-877e-143590c9f055 associated to the search application: Search Service Application on server: VDIGL070404 has failed. The component version is not compatible with the search database: Search_Service_Application_CrawlStoreDB_4925b8b4b5574940ba8389bffd59423f on server: VDIGL070404. The possible cause for this failure is The database schema version is less than the minimum backwards compatibility schema version that is supported for this component. To resolve this problem upgrade this database..


In order to update the SharePoint databases, you must manually run the PSconfig utility. To run the utility:
Check if the server needs update with the following command in the sharepoint powershell admin,
                   
                       (get-spserver $env:computername).NeedsUpgrade

If it returns TRUE, then follow the steps below
1. Open an Administrative command prompt.
2. Change directory to C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\BIN
3. Run PSConfig.exe -cmd upgrade -inplace b2b -force -cmd applicationcontent -install -cmd installfeatures

This may take couple of minutes to finish.

http://social.technet.microsoft.com/Forums/en-US/smallbusinessserver/thread/94c5f178-f020-4d0f-ba7c-11c415d0d862/


  Subscribe

Wednesday, July 18, 2012

setting custom list forms to content type

Share/Save/Bookmark


Setting custom display/edit list forms to a content type

What i was aksed to do is if i can create custom form pages that can be set to the items of specific content type. Though i'm not sure of the second part im started with first part,creating the custom form for displayform.aspx.
So, I copied the existing form and added my custom control to it.
I tred to place the new form(customdisplayform.aspx) in the same location(listname\forms\) where OOB forms exist for a library/iist through a feature.
Though feature deploys the form to the location, i see the listformwebpart missing when i open the form in sharepoint designer.
Also, i have to set the propertiesand ListName and ListId of listformwebpart dynamically, so i decided to go for a application page with code behind in which the properties are set onInit as below.

listFormWP.ListName = SPContext.Current.Web.Lists["lib"].ID.ToString();

listFormWP.ListId = SPContext.Current.Web.Lists["lib"].ID;
Now, application page will have the same markup as is just that it will inherit layoutspagebase class.
so now we have the form ready but how to associate with the library or list? here is the code,

SPList list = web.Lists["lib"];
list.DefaultEditFormUrl = "/../_layouts/mlp/CustomEditForm.aspx";

list.DefaultDisplayFormUrl = "/../_layouts/mlp/CustomDisplayForm.aspx";

list.update();

Custom list forms can also be associated to content type as below,

SPContentType reportCT = list.ContentTypes[contentType];


reportCT.DisplayFormUrl = "/../_layouts/mlp/CustomDisplayForm.aspx";

reportCT.EditFormUrl = "/../_layouts/mlp/CustomEditForm.aspx";

reportCT.Update();

Please let me know if anybody found something on the missing markup issue when custom list form is provisioned inside the path of the library rather under layouts.

 Subscribe

Tuesday, May 22, 2012

Binding objectdatasource to SPGridView for Sorting

Share/Save/Bookmark

Today I have a simple requirement, to achieve filtering and sorting on a simple grid.
Asp.Net GridView do not have an option to filter by default but where as SPGridView provides as part of the control.
I have simple method, that will form the data into DataTable which will be set as datasource to SPGridView as shown in below code.



<SharePoint:SPGridView runat="server" ID="reportsList" AutoGenerateColumns="false"PageSize="1" AllowPaging="false"
AllowSorting="true"  AllowFiltering="false" FilterDataFields="Col1,Col2,Col3,Col4" >
    <Columns>
        <asp:TemplateField HeaderText="Col1" SortExpression="Col1">
            <ItemTemplate>
                <asp:HyperLink ID="Col1Link" runat="server" Text='<%# Eval("Col1") %>'NavigateUrl= '<%# Eval("Col5") %>'   />
            </ItemTemplate>
        </asp:TemplateField>
            <asp:TemplateField HeaderText="Col2" SortExpression="Col2">
            <ItemTemplate>
                <asp:HyperLink ID="TabLink" runat="server" Text='<%# Eval("Col2") %>'NavigateUrl= '<%# Eval("Col6") %>'  />
            </ItemTemplate>
        </asp:TemplateField>
                                   
        <SharePoint:SPBoundField HeaderText="Col3" SortExpression="Col3" DataField="Col3" />
        <SharePoint:SPBoundField HeaderText="Col4" SortExpression="Col4" DataField="Col4" />
    </Columns>
    <EmptyDataTemplate>   No data.</EmptyDataTemplate>
</SharePoint:SPGridView>


above markup is also an example for binding hyperlink fields in spgridview.

protected override void CreateChildControls()
        {
            base.CreateChildControls();
            using (SPSite site = new SPSite(SPContext.Current.Site.Url))
            {
                using (SPWeb web = site.OpenWeb())
                {
                  
                    // bind the datasource to grid
                    reportsList.DataSource = GetMyDataTable();
                    reportsList.DataBind();
                  
                }
            }
           
        }
So easy and simple to see the grid populated with data on the page, but when I choose to sort a column I get the below error .
The GridView 'GridViewID' fired event Sorting which wasn't handled
Googling around I found that property, DataSourceID need to set instead of setting DataSource. Not sure why.
So now I have to rewrite the code and bind some type of datasource(objectdatasource/SPdatasources/…/).
As we know, ObjectDataSource is simple and easy I started with it and then lately realized that I have to create objects, I mean new type that will be used by ObjectDataSource as suggested by all other blogs.
But I do not want to write extra code but directly bind the existing datatable as objectdatasource for which blogs suggest to create type and write a method that will convert it to datatable which seem to be round way for me.
So I tried the below code and able to achieve sorting without a new Type/object definition. Still i could not get filtering work..at least it did not throw any error in log or on page.


//populate the datasource
                    ObjectDataSource  reportsDataSource = new ObjectDataSource();
                    reportsDataSource.ID = "reportsDataSource";
                    reportsDataSource.SelectMethod = "GetMyDataTable";
                    reportsDataSource.TypeName = this.GetType().AssemblyQualifiedName;
                    this.Controls.Add(reportsDataSource);
                    
                    // bind the datasource to grid
                    reportsList.DataSourceID = "MyDataSource";//  = 
                    reportsList.DataBind();


 Subscribe

Sunday, May 6, 2012

Read SharePoint Service using JQuery

Share/Save/Bookmark


I had spent a day to know that soap response can be read at the event complete but not success.
In success event soapresponse(data.responseXML) is always empty. I'm not sure if its a sepcial case with soap.

Below function of Jquery retrieves the SocialTag count of a specific URL from all users.
Complete event triggers all the time after the service call resulting in success or error. So i used a flag based on which i can get to know if the service call is success or error.

function GetLikeCountFromService(domId, url) {

var tagName = "I like it";
var queryStatus = true;


var soapEnv =
"<soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'>\
<soap:Body> \
<GetTagTermsOnUrl xmlns='http://microsoft.com/webservices/SharePointPortalServer/SocialDataService'>\
<url>" + url + "</url>\
<maximumItemsToReturn>'100</maximumItemsToReturn> \
</GetTagTermsOnUrl> \
</soap:Body> \
</soap:Envelope>";

$.ajax({
url: '/_vti_bin/socialdataservice.asmx',
type: 'POST',
dataType: "xml",
data: soapEnv,
complete: function (data) {

//process only if the query is success
if (queryStatus) {
var likeCount = 0;
$(data.responseXML).find("SocialTermDetail").each(function () {
var term = $(this).find("Term").find("Name").text();
//alert($(this).find("Term").find("Name").text());
if (term == tagName) {
likeCount = $(this).find("Count").text();
// set the like count
$(domId).text(likeCount);
return;
}
});
,

error: function (all, textStatus, errorThrown) { queryStatus = false; alert(errorThrown); },
contentType: "text/xml; charset=\"utf-8\""
});
}



JQuery made life easy with flexible API. I have implemented another function similar to it that will like a URL, in sharepoint terms tagging a url with "I Like It". As a combination this will work as similar to the Social Like feature in Facebook.

Subscribe