Monday, October 25, 2010

Error: File not found when address the site with full computer name

Today, I have an interesting thing while I am working on SharePoint. My co-worker gets an error when he try to access the SharePoint site by IP address. Of course, he can fix this issue, that means it's so easy, at least with him. However, it still shows error if I address to his site with full computer name. You know, when your computer join to the domain, then your computer's fullname is your computer name dot domain name.

In this example, my computer name is htserver2k8x64 (or vm_moss2007x64), when I join to the domain with named "tuan-tomy-blogspot.vn" then my computer's fullname is "vm_moss2007x64.tuan-tomy-blogspot.vn". The problem is if I browse my site from http://vm_moss2007x64 or http://htserver2k8x64 (for windows server 2008, 64 bits), everything works fine. After that I changed to http://vm_moss2007x64.tuan-tomy-blogspot.vn, with the team site without my web part that everything is fine again. But if in the team site included my web part already, I got an error like this:

Then, I removed my web part out web part zone, then added my web part again, I got another error:


Yeah! for now I just did the following SharePoint instruction. In this case, I must add new alternating access mapping in the Central Admin.
Go to Options -> Alternating Access Mapping -> Add internal URL for Port 80 ( I am working on Port 80)

Then you will see 2 internal url can access to the same web application:

For now, you can access the site by http://vm_moss2007x64 or http://vm_moss2007x64.tuan-tomy-blogspot.vn without any error.

------------------
For another solutions, you can modify the Host header of your site in IIS:


This solutions is also resolved this issue.


Error: The security validation for this page is invalid. Click Back in your Web browser, refresh the page, and try your operation again

Today, I try to create a hidden list and then get its schema. My purpose is to know how many columns in each of list type. But I did not logged in the site by owner, just used  Contribute account to do creating. Unfornately, Contribute account does not have the right to create a new list, only can create a new view or new item in the list. So, I get the error if I try to create:

[COMException (0x8102006d): The security validation for this page is invalid. Click Back in your Web browser, refresh the page, and try your operation again.]


Now, take a look at my code:

After search on the internet, I read the blog from: Tushar Parikh. He recommended to re-config Security of the Web Application:

Central Administration -> Application Management -> Web Application General Settings ->Select web application

In Web Page Security Validation , change security validation is off. 


I tried the following his instruction and it worked for me, but the another problem is just worked for PostBack page. But in recent, my page is running under ajaxified. So, I must turn the security validation on. But I found another blog and I resolved the problem.

Here is the blog:
http://community.bamboosolutions.com/blogs/bambooteamblog/archive/2008/05/15/when-allowunsafeupdates-doesn-t-work.aspx

My code was changed:

AllowUnsafeUpdates property is very useful if you want to update the property bag of Web or Site object. It takes me 1 hour to research and fix the problem... Thanks for all

Monday, October 18, 2010

How is the Attachment column worked in CAML query?

It took me a few minutes to fix this issue.

SharePoint did not allow you filter the value of attachment column with another value except for "Yes" or "No". But when you bind data into a gridview with filtering option is ON, user still can type or filter this column with another value, for example: Greater than "5" or Less Than "OK"

1) Greater Than "5" Our CAML query is


Result: No record is displayed. That would be nice. But when you change Less Than "5", it would be:



You know, with Attachments column, if the item has an attachment, its value is 1 and otherwise is 0. So, the CAML query is less than "5" matched with items which have both an attachment and none. That's very funny.


2) Less Than "OK"




I really dont know how the SharePoint parsed this value, but it will show data with items which has no attachment.

Conclusion: When you want to return "No record" if user filters with the value different from "Yes" / "No" or "1" / "0" the value in CAML query must be "." (dot) 

Yeap. It worked for me now.




Wednesday, October 13, 2010

Best Practices for Writing JavaScript in SharePoint 2010

JavaScript is an important part of building any interactive website, and SharePoint is certainly no exception. With SharePoint, JavaScript is often used to execute code on the client and it is usually designed to affect only one specific Web Part, as opposed to affecting an entire page. So, in a typical SharePoint page where there are many Web Parts in a zone, it's very easy to mistakenly write Java code that affects another Web Part.  The potential for such conflicts is unavoidable, so this article details some best practices for working on JavaScript and SharePoint Web Parts in SharePoint 2010.

http://community.bamboosolutions.com/blogs/sharepoint-2010/archive/2010/10/14/best-practices-for-writing-javascript-in-sharepoint-2010.aspx


Full article here

Tuesday, October 12, 2010

Error javascript if RadGrid binds data with Ajaxified and filtering is ON (SharePoint 2010)

Problem:


I have an UI to allow user to select a list and bind the data into grdiview. The button create will run under Ajax.

If you are using RadGrid with ajaxified in the package Telerik.Web.UI.Dll (2010.1.415.35), but did not bind the data into grid until the configuration finished, you will get the error like this: (this error just happens with filtering function is ON).

Note: Just happen on SharePoint 2010 (both of SharePoint Foundation and Office SharePoint Server)



In fact, you still see the data on gridview but some functions on grid did not work correctl such as the filtering menu is stopped working.



Symptom:

After binding data, RadGrid added a lot of javascript resources in page need to run all functions. However, these resources will not be added after binding data under ajaxified.



Solutions:

When the setting page is showing, we bind the empty data (because the grid view does not show on the page, so we can bind with any data), here I am using a simple data with one column)

//This code should be put in OnLoad() method
//and just run for the first time
//when we click on Create button, the radGrid will bind from table after collecting data
//and these code will bypassed.

if (!Page.IsPostBack)
{
   DataTable tb = new DataTable();
   tb.Columns.Add("col1");
   GridDataBound col = new GridDataBound()
   col.HeaderText = "Col1";
   col.DataField = "Col1";
   col.UniqueCol = "Col1";

   radGrid.Columns.Clear();
   radGrid.MasterTableView.Columns.Add(col);
   radGrid.DataSource = tb;
   radGrid.DataBind();
}


//Events for create button
 protected void Create_Click(object sender, EventArgs e)
{
   //Collecting data
   radGrid.DataSource = tb;
   radGrid.DataBind();
}

The purpose to bind data at the first time is to generate the JavaScript resources by RadGrid. The next step is running under Ajax, so these resource will not update after that. But we can use the filtering function correctly.

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.