Friday, September 17, 2010

Redirect to link to new item with ContentType in SharePoint 2010

If you are working on SharePoint 2010 with Ribbon Menu, you will never see the action of each item menu on Ribbon. Thus, it's a little bit difficult to get the link or the JavaScript function to redirect to the target of action. This topic will describle the links of new item in ContentType.



In SharePoint 2010 has a lot of ContentTypes defined for List and library, if the name of contenttype has one of these value:

Basic Page: /_layouts/bpcf.aspx?List={YOUR_LIST_ID}&RootFolder=YOUR_ROOT_FOLDER &ContentTypeId=ITEM_CONTENTTYPE_ID&Source=URL_RETURNS

Web Part Page: /_layouts/spcf.aspx?List={YOUR_LIST_ID}&RootFolder=YOUR_ROOT_FOLDER &ContentTypeId=ITEM_CONTENTTYPE_ID&Source=URL_RETURNS

Master Page:  (or)
Picture:
javascript:NewItem2(event,"/_layouts/upload.aspx?List={YOUR_LIST_ID} &RootFolder=YOUR_ROOT_FOLDER &ContentTypeId=ITEM_CONTENTTYPE_ID&Source=URL_RETURNS&IsDlg=1");


Link to a Document:
javascript:NewItem2(event,"/_layouts/NewLink.aspx?List={YOUR_LIST_ID} &RootFolder=YOUR_ROOT_FOLDER &ContentTypeId=ITEM_CONTENTTYPE_ID&Source=URL_RETURNS&IsDlg=1");

List View Style:
Dublin Core Columns:
javascript:EditItem2(event,"/_layouts/Upload.aspx.aspx?List={YOUR_LIST_ID} &RootFolder=YOUR_ROOT_FOLDER &ContentTypeId=ITEM_CONTENTTYPE_ID");

Summary Task:
New Folder:
New Item:
javascript:EditItem2(event,"/_layouts/listform.aspx?ListId={YOUR_LIST_ID} &RootFolder=YOUR_ROOT_FOLDER &ContentTypeId=ITEM_CONTENTTYPE_ID");

Report Builder Model:

javascript:CoreInvoke('createNewDocumentWithRedirect2', event, '/_layouts/ReportServer/NewReportBuilderModel.smdl','YOUR_ROOT_WEB', 'SharePoint.OpenSmdlFiles', false,'/_layouts/ReportServer/GenerateModel.aspx?RelativeModelUrl= /_layouts/ReportServer/NewReportBuilderModel.smdl',false,1)

Report Data Source:

javascript:CoreInvoke('createNewDocumentWithRedirect2', event, '/_layouts/ReportServer/NewSharedDataSource.rsds','YOUR_ROOT_WEB', 'SharePoint.OpenRsdsFiles', false,'/_layouts/ReportServer/SharedDataSource.aspx?RelativeDataSourceUrl= /_layouts/ReportServer/NewSharedDataSource.rsds',false,1)

Report Builder Report:
javascript:CoreInvoke('createNewDocumentWithRedirect2', event, '/_layouts/ReportServer/rs.rsapplication', 'YOUR_ROOT_WEB', 'SharePoint.OpenRdlbFiles', false, '/_layouts/ReportServer/RSAction.aspx?RSAction=ReportBuilder&FileUrl=/_layouts/ReportServer/rs.rsapplication', false, 1)";

Note: YOUR_ROOT_WEB is the root web, ex: http://servername or http://servername:8080

Hope to waiste the less time to find out them.

Wednesday, September 15, 2010

How to create a popup window like SharePoint 2010 popup

Everytime we want to create or configure out something on SharePoint 2010 site, Microsoft will show a popup window with the forms according to our action. It looks like:


So, if you want to use popup like SharePoint 2010, it's very easy, just copy and paste the code below:

<a href="javascript:NewItem2(event, your_url)">click example</a>

However, you will only get the default of windows size in the popup. If you want to resize that popup to be smaller or bigger, you must use another function.

<a href="javascript:OpenPopUpPageWithTitle(your_url, CallBackFunction, width, height, null)">Click example</a>

The code above just describe how to open the windows and execute the javascript code after window loading completely. Now, the another purpose is to execute an another javascript function after close window. how to?

You can custom this method with any actions as you want, here is example:

if (typeof SP.UI.Dialog.close == 'function') {
    var old = SP.UI.Dialog.close;
    SP.UI.Dialog.close = function(dlgResult) {
        //TODO: your code here
        //Remember that, your code must be executed before calling original method, because original method will close your popup before you perform something.
         old();
    }
}

Here are some method extracted from SP.UI.Dialog

.get_firstTabStop();
.get_lastTabStop();
.get_url();
.get_html();
.get_title();
.get_args();
.get_allowMaximize();
.get_showClose();
.get_returnValue();

.set_returnValue(value);

....
Good luck to you!

Friday, September 10, 2010

How to get a property and call a method of class using reflection

Sometime you get an error when declare an object belongs to class, but before declare an object you must add that dll as a reference. but the problem is whether that dll is existed or not and what happend if that dll does not exist? On hundred percent is to throw exception because you are calling a method or property of object but it does not initialize. The best way is to reflect that class to object and not necessary to add that dll as reference.

I have a dll was built from the project named "example", here is the code


namespace Example
{
    public class Calculate
    {
        public Calculate()
        {
        }


        private int a = 0;
        public int A
        {
            get
            {
                return this.a;
            }
            set
            {
                this.a = value;
            }
        }


        private int b = 0;
        public int B
        {
            get
            {
                return this.b;
            }
            set
            {
                this.b = value;
            }
        }


        public int Plus()
        {
            return this.A + this.B;
        }


        public int Multiple()
        {
            return this.A * this.B;
        }


        public int Substract()
        {
            return (this.A - this.B);
        }


        public int Divide()
        {
            if (this.B == 0) throw new ApplicationException("Do not allow null !");
            return this.A / this.B;
        }
    }
}

The class is very simple to execute the calculating 2 numbers A and B. Now I have another project need to use this class, but I dont want to add this dll into my reference. If this dll was not installed, you will get an error when you build this project. So, I have another way, look at my code



        Type asmCal = asm.GetType("MyReflection.Calculate");


        object obj = Activator.CreateInstance(asmCal);


        //here you can detect obj and asmCal are not null before doing any thing bellow
        //set A property
        asmCal.InvokeMember("A", BindingFlags.SetProperty | BindingFlags.Public | BindingFlags.Instance, null, obj, new object[] { 5 });


        //set B property
        asmCal.InvokeMember("B", BindingFlags.SetProperty | BindingFlags.Public | BindingFlags.Instance, null, obj, new object[] { 5 });


        int plus = (int)asmCal.InvokeMember("Plus", BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod, null, obj, null);

Thursday, September 9, 2010

How to extract properties of webpart from any site.

We design a toolpane for webpart by adding a lot of toolparts into toolpane. We can design any layout as we want, but with the width of toolpane it's really difficult to design a complexity interface, so I want to introduce a new layouts  that can be designed very complexity.


In this topic, I give you a default security that user can open site with the currently right.

With a original toolpane, just add a button named "Modify Web Part" and after click on that button there is a new window appear and show your layouts need to define everything as needed. In this topic, assume that the  page to modify toolpane is called "modify.aspx".

This page, we need to know which webpart need to modify, so we will send to modify.aspx two parameters as query string [page, wpGuid]. In onclick event of "Modify Web Part" button, we could open a window like this:

window.open("modify.aspx?page=http://server/test/site.aspx&wpGuid=8230-12344-1111111xxxxx");


To extract all properties of web part, we need to get web part object first, here is the code:





public MyWebPart GetWebPart()
{
     try
     {
       string page = Convert.ToString(this.Page.Request.QueryString["page"]);

       string wpGuid = Convert.ToString(this.Page.Request.QueryString["wpGuid"]);

       if (page != "" && wpGuid != "")
       {
          using (SPSite site = new SPSite(page))
          {
              using (SPWeb web = site.OpenWeb())
              {
                  using (SPLimitedWebPartManager pageWebParts = web.GetLimitedWebPartManager(page, System.Web.UI.WebControls.WebParts.PersonalizationScope.User))
                  {
                      try
                      {
                         SPLimitedWebPartCollection webParts = pageWebParts.WebParts;
                         foreach (WebPart wpart in webParts)
                         {
                            if (wpart.StorageKey.ToString().Equals(wpGuid))
                            {
                                 return (MyWebPart)wpart;
                             }
                         }
                       }
                       finally
                       {
                            pageWebParts.Web.Dispose();
                       }
                    }
                }
           }
         }
       }
       catch 
       {
                //your exception
       }
       return null;
   }

But in some case, the [Page] parameter is incorrect format, sometime it would be missing /default.aspx or page.apsx or any prefix.aspx, and the code above will not work. So, we need to identify the url to pass it for SPSite object. The code bellow is to show what we need to do:




public MyWebPart GetWebPart()
        {
            try
            {
                string page = Convert.ToString(this.Page.Request.QueryString["page"]);

                string wpGuid = Convert.ToString(this.Page.Request.QueryString["wpGuid"]);

                if (page != "" && wpGuid != "")
                {
                    using (SPSite site = new SPSite(page))
                    {
                        using (SPWeb web = site.OpenWeb())
                        {
                            using (SPLimitedWebPartManager pageWebParts = web.GetLimitedWebPartManager(page, System.Web.UI.WebControls.WebParts.PersonalizationScope.User))
                            {
                                try
                                {
                                    SPLimitedWebPartCollection webParts = pageWebParts.WebParts;
                                    foreach (WebPart wpart in webParts)
                                    {
                                        if (wpart.StorageKey.ToString().Equals(wpGuid))
                                        {
                                            return (MyWebPart)wpart;
                                        }
                                    }
                                }
                                finally
                                {
                                    pageWebParts.Web.Dispose();
                                }
                            }
                        }
                    }
                }
            }
            catch // it throw exception when the configuration server is http/https
            {
                return GetWebPartAgain();
            }
            return null;
        }

private MyWebPart GetWebPartAgain()
        {
            string url = Convert.ToString(this.Page.Request.QueryString["page"]);

            string wpGuid = Convert.ToString(this.Page.Request.QueryString["wpGuid"]);

            using (SPSite site = new SPSite(url))
            {

                using (SPWeb web = site.OpenWeb())
                {
                    SPFileCollection files = web.Files;

                    foreach (SPFile file in files)
                    {
                        using (SPLimitedWebPartManager pageWebParts = file.GetLimitedWebPartManager(System.Web.UI.WebControls.WebParts.PersonalizationScope.User))
                        {
                            try
                            {
                                SPLimitedWebPartCollection webParts = pageWebParts.WebParts;
                                foreach (WebPart wpart in webParts)
                                {
                                    if (wpart.StorageKey.ToString().Equals(wpGuid))
                                    {
                                         return (MyWebPart)wpart;
                                    }
                                }
                            }
                            finally
                            {
                                pageWebParts.Web.Dispose();
                            }
                        }
                    }
                }
            }
            return this.Context.Request.Url.ToString();
        }

When you get the Webpart object, you can extract its properties and work anything on that. After changes, you can serialize all changes into an xml string and return the function called the page modify.aspx. A hidden field will catch this xml string and store into a property of toolpart. Every time open modify.aspx, you can deserialize to work on that.

Good luck to you.

Wednesday, September 1, 2010

How to check URL is relative or absolute path

The relative path is a part of following format:


1)  ~/ or / : is the root site


ex: http://serverA/site1/site2/site3/default.aspx, with the current site is Site3, then ~/ will return http://serverA


2) ./: is the current site


3) ../: is the parent site


with above example will return http://serverA/Site1/Site2


The problem is how to check the input url whether using relative path or absolute path.


The simple code can be like this:


public bool IsRelative(string url)
{
    return (url == "~/" || url == "/" || url == "./" || url == "../");
}


But if you want to make sure the functioning work correctly, it should be:



public static bool IsUrlRelative(string url)
{
    Uri uri;
    try
    {
        uri = new Uri(url, UriKind.RelativeOrAbsolute);
    }
    catch
    {
        return false;
    }
    return !uri.IsAbsoluteUri;
}

For now, SharePoint has supported the class to check this, it's very helpful:

SPUrlUtility supported some methods to work on URL:

public static string CombineUrl(string baseUrlPath, string additionalNodes);

return the concatenate 2 string

public static int IndexOfIllegalCharInUrlLeafName(string strLeafName);

return the position of illegal character in your string

public static bool IsLegalCharInUrl(char character);

indicate your character is legal or not

public static bool IsLegalFileName(string name);

indicate your file name is legal or not

public static bool IsProtocolAllowed(string fullOrRelativeUrl);

public static bool IsProtocolAllowed(string fullOrRelativeUrl, bool allowRelativeUrl);
public static bool IsUrlFull(string url);
public static bool IsUrlRelative(string url);

Sunday, August 15, 2010

A simple way to install a SharePoint Farm server.

A SharePoint Farm includes many SharePoint server join into the server which is hosting the Central Admin. However, the servers which joined into the server also can host the Central Admin. A SharePoint Farm only use one a SQL box and can share the resources, data, security,...


This is a simple way to install a sharepoint farm with a highest security and make your server to be safer.

Before installing the farm, create 2 accounts in domain named sqlaccount and spinstaller
Prepare 3 computers: C1, C2 and C3.


We will install MS SQL on C1, SharePoint server hosts Central Admin on C2 and a child server on C3 to join in C2.

Step 1: Login on C1 by Administrator (Local Admin) and install SQL Server
Step 2: Login on C2 by Administrator (Local Admin) and add the account spinstaller into Local Administrators Group.


Step 3: Login on C2 again by spinstaller to install SharePoint. Remember to select Web Front-End option when you install SharePoint.


Step 4: After the installing progress finish, run the SharePoint configuration wizard, type the SQL Server name, database name and use sqlaccount to config the SharePoint.

Step 5: Login on C3 by spinstaller (also add this account into Local Administrators Group) to install SharePoint and select Web Front-End option.


Step 6: Run the SharePoint configuration wizard on C3. At this time, the wizard will ask you to install the new server or connect to existed server. Click on Connect to Existed server. Type the SQL Server and lick Retrieve database, you will get the SharePoint_Config database (that is already existed on C1), type the account sqlaccount to wizard finish the configuration.


That's all. Good luck.

Monday, August 9, 2010

Can not print DIV background & TABLE layout

Sometime, you wonder why could not print the background of DIV and TABLE. Of course, you will take a look at your HTML code, or read the article on MSDN or found something on the internet after google the key of issue.

If you can not print the background or the layout you saw after review the print then please do as a following things:

1) Be sure that DTD is referenced correct. I mean if you are working on Master Page (it's often used the DTD to format the layout). It look likes:

Some DTDs disable or enable some of attributes of DIV tag and TABLE. Sometime you can not get its offsetWidth or its offsetHeight because of using DTD.

2) Ensure that your browser allow to print the background

For IE: go to menu Tool -> Internet Options -> Click on Advanced Tab -> Scroll down and check Print Background
3) Check the code.
If you never use DTD to re-design your layout, you should check the following things:
Please take a look at code:



<div style="float: left; height: 50px; width: 75px;">
Hello</div>



^lt;div style="float: left; height: 50px; width: 125px;">
How are you doing?</div>


When you print or print-review, you only see Hello or even nothing is shown on area printable. When you use float:left, print media did not understand that attribute, so the height of DIV will increase and pull down the text, you won't see the data. 


Solutions: just change DIV to SPAN and remove "float:left" or "float:right"




<div style="overflow: hidden;">

your HTML content
</div>



When you print or review, the content shows like this:

Even thought you had been formatted the layout as well.
Solutions: just remove the overflow:hidden

Saturday, July 31, 2010

Can not save properties WP in publishing site...

There's the interesting thing when you are a developer based on SharePoint that why do not save the properties of Web Part if it is publishing site template.

Of course, when you save the properties at the runtime, you must set SaveProperties = true to apply the any changes.

But in publishing site, before doing any changes on WP, you must do check out and after finish changing to do check in. At the same time, only one user can be checked-out/checked-in to avoid the conflict.

.....

Một điều thú vị mà ai khi lập trình SharePoint cũng sẻ hỏi là, tại sao không lưu được các thuộc tính của webpart khi sử dụng template Publishing Site.

Dĩ nhiên, khi thực hiện thao tác lưu thuộc tính của webpart cho dù runtime hay không thì việc s73 dụng thuộc tính SaveProperties = true cũng chẳng ảnh hưởng nhiều, mục đích chỉ để Apply những thì đã thay đổi.

Trong publishing site, muôn lưu lại các thuộc tính của WP thì truoc tiên phải Check Out site đó ra, rồi thao tác trên WP, sau khi thao tác xong, nhớ check in lên; Tại 1 thời điểm chỉ có 1 user có thể check out và check in để tránh conflict.

Tuesday, July 27, 2010

SPSiteDataQuery error on Discussion Board List

SPSiteDataQuery is used to get the data from multiple list with the same type. The code below shows how to get all items in Discussion Board List. Only show Subject and ID after returning data.

SPSiteDataQuery query = new SPSiteDataQuery();


query.ViewFields = "<FieldRef Name=\"LinkDiscussionTitle\"/><FieldRef Name=\"ID\"/>";
query.Lists = "<Lists ServerTemplate=\"108\"/>";


DataTable table = web.GetSiteData(query);

But you will get an error like this:


AAAAA.Data.UnitTest.GetInternalName.GetDataFromDB : Microsoft.SharePoint.SPException : Exception occurred. (Exception from HRESULT: 0x80020009 (DISP_E_EXCEPTION))
  ----> System.Runtime.InteropServices.COMException : Exception occurred. (Exception from HRESULT: 0x80020009 (DISP_E_EXCEPTION))


The details:



 at Microsoft.SharePoint.Library.SPRequest.CrossListQuery(String bstrUrl, String bstrXmlWebs, String bstrXmlLists, String bstrXmlQuery, ISP2DSafeArrayWriter pCallback, Object& pvarColumns)
   at Microsoft.SharePoint.SPWeb.GetSiteData(SPSiteDataQuery query)
   at Bamboo.Data.UnitTest.GetInternalName.GetDataFromDB() in D:\BambooFolder\TFS2008\Bamboo.WP.ListConsolidator\Bamboo.ListConsolidatorSoln\Bamboo.Data.UnitTest\GetInternalName.cs:line 168
--COMException
   at Microsoft.SharePoint.Library.SPRequestInternalClass.CrossListQuery(String bstrUrl, String bstrXmlWebs, String bstrXmlLists, String bstrXmlQuery, ISP2DSafeArrayWriter pCallback, Object& pvarColumns)
   at Microsoft.SharePoint.Library.SPRequest.CrossListQuery(String bstrUrl, String bstrXmlWebs, String bstrXmlLists, String bstrXmlQuery, ISP2DSafeArrayWriter pCallback, Object& pvarColumns)


The LinkDiscussionTitle is one of the internalname of Discussion Board List, but if you try to query by that column, you will get an error. You can query by any column, except for LinkDiscussionTitle. Just remove that column out your query string, it works fine.

SPSiteDataQuery has been supported all functions like SPQuery exception for GroupBy, if you try to put the GroupBy clause into query, it will throw exception but you can work with filtering and sorting.

Sunday, July 25, 2010

Những cách viết hay JavaScript trong SharePoint - Phần 3

3) Đăng ký StartUpScript hay BlockScript

Có rất nhiều lý do chúng ta đăng 1 đoạn script, thông thường trong C# có 4-5 cách để đăng ký. Đôi khi, lập trình viên cứ quen cách viết mặc định là ClientScript.RegisterClientScriptBlock, tác hại là code không chạy được, bỗng dưng...bực bội.

Tham khảo đoạn code sau nha:

<form action="page.aspx?...">

<script language="javascript">
var myWP = document.getElementById("ms-WP01");
var myCal = myWP.getElementsByTagName("DIV");
myCal[0].style.border = "1px solid red";
</script>

<div id="ms-WP01">
<div id="182C-0123-DB46EF67687-021C" class="ms-cal">
....
</div>
</div>

</form>

Lúc chạy trang web IE nó báo error JavaScript vàng khè ở thanh status bar, click đúp vào thì thấy "myWP is null or undefined", còn chạy Firefox thì im um bà rù.

Thắc mắc: code mình không sai, dò lại thấy trong hàm OnPrerender viết như sau

string strCode = @"var myWP = document.getElementById("ms-WP01");
var myCal = myWP.getElementsByTagName("DIV");
myCal[0].style.border = "1px solid red";";
if (!Page.ClientScript.IsRegisterClientScriptBlock("MyCode"))
{
Page.ClientScript.RegisterClientScriptBlock(this.getType(), "MyCode", strCode, true);
}

Lạ nhỉ, code đúng, build thành công nhưng chạy thì nó báo lỗi. Đơn giản thôi vì cái code JavaScript nó chạy từ trên xuống, đến đoạn nào thực thi ngay đoạn đó, code của chúng ta chạy cũng chẳng có gì phức tạp. myWP chắc chắn sẽ null, vì đến khi chạy lúc đó đối tượng ms-WP01 chưa được Render ra, document nó chưa hiểu ms-WP01 là cái mô tê gì hết.

Do vậy, để tránh những trường hợp thế này chúng ta nên để ý, đoạn code chúng ta đặt ở vị trí nào cho phu hợp, trong trường hợp này chúng ta đặt ở vị trí trước khi kết thúc tag FORM, nghĩa là dùng hàm RegisterStartUpScript, thì mọi chuyện được giải quyết êm xui.

Chúc các bạn thành công.