ASP.NET Ajaxを利用したWebPartのサンプル
RSSリーダをASP.NET Ajaxのクライアントサイドフレームワークで作成しWebPart化するシナリオです。
クライアントサイドでコントロールを作成するのはASP.NET Ajaxの知識範囲でOK。WebPart化する場合のポイントはScriptManagerの取扱い方法に工夫が必要な程度で、それほど特別な点はなし。
以下参考書籍です。
Inside Microsoft Windows SharePoint Services Version 3.0
作成手順
例)
ASP.NET Ajaxクライアントサイドフレームワークでクライアントサイドのコントロールを作成
以下のようなJavaScriptファイルを作成し、ビルドアクションを"埋め込まれたリソース"にする
//名前空間の登録 Type.registerNamespace('SampleAjaxWebPart'); //クラス(コンストラクタ関数)の宣言 SampleAjaxWebPart.AjaxRssControl = function(element) { SampleAjaxWebPart.AjaxRssControl.initializeBase(this, [element]); this._element = element; this._feedCount = 3; this._url = null; } //メソッドの定義(プロトタイプに定義) SampleAjaxWebPart.AjaxRssControl.prototype = { initialize : function() { SampleAjaxWebPart.AjaxRssControl.callBaseMethod(this, 'initialize'); this.request(); }, // 後処理 dispose : function() { SampleAjaxWebPart.AjaxRssControl.callBaseMethod(this, 'dispose'); }, request : function() { if (this.get_Url() == null) return; if (this.get_Url() == "") return; var wRequest = new Sys.Net.WebRequest(); wRequest.set_url(this.get_Url()); wRequest.set_httpVerb("GET"); this._webRequestCompletedHandler = Function.createDelegate(this, this._onWebRequestCompleted); wRequest.add_completed(this._webRequestCompletedHandler); wRequest.invoke(); }, _onWebRequestCompleted : function(executor, eventArgs) { if(executor.get_responseAvailable()) { var displayElement = this._element; var items = executor.get_xml(); var items_count; if ((this._feedCount == 0) || (this._feedCount > items.selectNodes('//item').length)) { items_count=items.selectNodes('//item').length; } else { items_count=this._feedCount; } var divHtml = ""; for(var i=0; i<items_count; i++) { var node; var title; node = items.selectNodes('//item')[i]; title = node.selectSingleNode('title').text; link = node.selectSingleNode('link').text; if (this.checkVisited(link)) { divHtml= divHtml+ "<a href='"+link+"'>■" + title +"</a><br/>"; } else { divHtml= divHtml+ "<a href='"+link+"'>□" + title +"</a><br/>"; } } displayElement.innerHTML = divHtml; } else { if (executor.get_timedOut()) displayElement.innerText = "Timed Out"; else if (executor.get_aborted()) displayElement.innerText = "Aborted"; } }, checkVisited : function(url) { //IE限定の処理ロジック var id = 'checkVisitedLinkId'; var style = document.createElement('style'); document.body.appendChild(style); var sheet = style.styleSheet; sheet.addRule( '#' + id + ':visited', '{display:none;position:absolute;top:0px}'); var link = document.createElement('a'); link.id = id document.body.appendChild(link); link.href = url; var ret = (link.offsetTop == 0); document.body.removeChild(link); document.body.removeChild(style); return ret; }, // プロパティ get_Url : function() { return this._url; }, set_Url : function(value) { if (this._url != value) { this._url = value; this.raisePropertyChanged('Url'); } }, get_FeedCount : function() { return this._feedCount; }, set_FeedCount : function(value) { if (this._feedCount != value) { this._feedCount = value; this.raisePropertyChanged('FeedCount'); } } } SampleAjaxWebPart.AjaxRssControl.registerClass('SampleAjaxWebPart.AjaxRssControl', Sys.UI.Control);
作成したクライアントサイドのコントロールをWebPart化する
using System; using System.Collections.Generic; using System.Text; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI; [assembly: WebResource("SampleAjaxWebPart.Controls.AjaxRssControl.js", "application/x-javascript")] namespace SampleAjaxWebPart.Controls { public class AjaxRssWebPart : WebPart { public ScriptManager AjaxScriptManager { get { if (_ajaxScriptManager == null) { _ajaxScriptManager = ScriptManager.GetCurrent(this.Page); if (_ajaxScriptManager == null) { _ajaxScriptManager = new ScriptManager(); this.Controls.AddAt(0, _ajaxScriptManager); } } return _ajaxScriptManager; } } private ScriptManager _ajaxScriptManager; private Panel div; [Personalizable(), WebBrowsable(), WebDisplayName("RSSのURL")] public string Url { get { return _url; } set { _url = value; } } private string _url; [Personalizable(), WebBrowsable(), WebDisplayName("表示数")] public int Count { get { return _count; } set { _count = value; } } private int _count; protected override void CreateChildControls() { base.CreateChildControls(); div = new Panel(); this.Controls.Add(div); ScriptReference controlScript = new ScriptReference( "SampleAjaxWebPart.Controls.AjaxRssControl.js", "SampleAjaxWebPart.Controls"); this.AjaxScriptManager.Scripts.Add(controlScript); StringBuilder sb = new StringBuilder(); sb.AppendLine("<script language=\"javascript\">"); sb.Append(" $create(SampleAjaxWebPart.AjaxRssControl, {"); sb.Append("\"Url\":\"" + _url + "\","); sb.Append("\"FeedCount\":" + _count); sb.Append("}, null, null, $get(\"" + div.ClientID + "\"));"); sb.AppendLine(); sb.AppendLine("</script>"); this.Page.ClientScript.RegisterStartupScript( this.GetType(), "AjaxRssControl" + div.ClientID, sb.ToString()); } protected override void Render(HtmlTextWriter writer) { if (base.DesignMode) { this.EnsureChildControls(); } this.RenderContents(writer); } } }
補足
このサンプルでは、クライアントサイドでRSSデータを取得しているため直接他サイトのRSSデータを読み込むことはできません。他サイトはサーバ経由でRSSデータを読み込む必要があります。
ただ、NTMLで同じサイトのMOSSのRSSデータを権限に応じて読みだすことができるメリットはあるかな。
追記
MOSSではリストアイテムの既読・未読がマークされません。
リンクのvisitedを利用した簡易的な既読/未読の判定を行うためのロジックを追加しました。これでMOSSでも既読・未読が表示できるようになるはずです。