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.

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

2) Overload / overwrite

Chúng ta rất thường sử dụng các sự kiện của window và document, ví dụ như window.onload, document.onload... Đôi khi chúng ta viết riêng thì code chúng ta chạy rất tốt, nhưng khi nhúng vào 1 web site có sẵn thì chúng không chạy được hoặc một số chức năng có sẵn của web đó không chạy được, chúng ta không biết vì sao...

Thật ra khi chúng ta viết code JavaScript, độ ưu tiên là code cuối cùng được khai báo trong trình duyệt, do vậy để code có sẵn của web chạy được và code của chúng ta cũng chạy được chúng ta nên viết như sau:

1) backup lại hàm đã có
2) kiểm tra có tồn tại hay không
3) overwrite lại sự kiện đó
4) gọi lại các hàm đã backup và hàm của chúng ta

Ví dụ: trong ví dụ này chúng ta giả sữ trong window.onload chúng ta cần làm một số việc và để trong hàm wOnload.


function wOnload()
{
//TODO: làm cái gì đó đi cho vui cửa vui nhà
}

var oldF = window.onload; //backup lại hàm cũ nha
if (oldF && typeof oldF == "function")
{
//Nếu có ai đó đã định nghĩa sẵn window.onload thì nó sẽ nhảy vào đây
window.onload = function(e) {
oldF(); // Gọi hàm người ta cho nó thực thi
wOnload(); // rồi thực thi hàm của mình
}
}
else {
//Nếu không có ai định nghĩa thì quất hàm của mình luôn
window.onload = wOnload;
}

Những cách viết hay JavaScript trong SharePoint

Bài viết này xin giới thiệu cho các bạn cách chúng ta viết Code JavaScript sao cho tốt nhất và ít đụng chạm đến code của người khác.

Đôi khi chúng ta viết code JavaScript mà để code độc lập riêng mình thì nó chạy rất tốt, nhưng khi gắn cái của mình vào những chỗ có sẵn, hoặc những có có JavaScript thì code của mình tịt ngòi, không chạy được, không rõ nguyên nhân. Vậy làm sao tránh gặp những lỗi rắc rối này?

1) Tránh giá trị Null

Đôi khi chúng ta không thể xác định được giá trị của biến mình đang dùng có bị null hay không, nhất là trong những trường hợp Corssbrowser.

Ví dụ: ở IE bạn có thể sử dụng parentElement nhưng Firefox và các trình duyệt khác không bao giờ biết parentElement là cái gì, tuy nhiên khi bạn viết parentNode thì tất cả trình duyệt đều hiểu và giá trị luôn khác null. Do đó, cách tốt nhất chúng ta nên viết là:

var pNode = this.parentElement || this.parentNode;

Hay như đối tượng event ( window.event), trình duyệt firefox không hiểu nó là cái quái gì hết, Firefox chỉ hiểu event chỉ khi nào đối tượng có xảy ra 1 sự kiện nào đó, và trong sự kiện đó lập trỉnh viên phải tự thêm một argument bất kỳ để firefox gửi đối tượng event vào trong đó.

Ví dụ:


trong JavaScript chúng ta có thể viết:

function dMouseOver()
{
var evt = window.event.srcElement;
}


Với Firefox code này bó tay, chúng ta phải viết lại




function dMouseOver(e)
{
var evt = e.srcElement;
}


Như vậy trong 2 cách viết đó, chúng ta phải gộp lại thành 1 code chuẩn duy nhất mà có thể chạy trên tất cả các trình duyệt




function dMouseOver(e)
{
e = e || window.event;
var evt = e.srcElement;
}