2012年12月26日 星期三

【SharePoint】判斷清單屬性


最近做一個SharePoint的功能,需要將SiteCollection裡面所有子網站的清單全數撈出來,並判斷是否為Survey或Announcement
  • 判斷是否為Survey
    List.BaseType.ToString() =="Survey"
  • 判斷是否為Announcement
       List.BaseTemplate.ToString() == "Announcements"
    

問卷 Survey
公告 Announcements
文件庫 DocumentLibrary



另外網路上查到各種清單的對照表,可以參考 : 清單對照表

【SharePoint】VisualWebPart




建立VisualWebPart(後面簡稱vwp)後會產生以下檔案結構


.XML檔中可以設定vwp佈署後歸類在哪個群組裡面


VWP的CS檔中可以增加可設定的參數
namespace ScinoPharm.EIP.vwpSurveys
   {
        [ToolboxItemAttribute(false)]
        public class vwpSurveys : WebPart
        {
            //增加可設定的參數
            [Category("MySetting"),
             Personalizable(PersonalizationScope.Shared), //共用設定
             WebBrowsable(true), //是否顯示在面板上
             WebDisplayName("來源清單名稱"),
             WebDescription("請填寫Survey資料來源的清單名稱") //描述
            ]

            public string ListName{get;set;}

            //當您變更視覺 Web 組件專案項目時,Visual Studio 可能會自動更新此路徑
            private const string _ascxPath = @"~/_CONTROLTEMPLATES/ScinoPharm.EIP/vwpSurveys/vwpSurveysUserControl.ascx";

            protected override void CreateChildControls()
            {
                Control control = Page.LoadControl(_ascxPath);
                ControlSkin.Add(control);
            }
        }
   }



在UserControl中要抓到VWP的參數設定,需要透過以下的方法
public vwpSurveys SurveyParameter;

    protected void Page_Load(object sender, EventArgs e) 
    {
        if (!Page.IsPostBack) 
        {
            SurveyParameter = this.Parent as vwpSurveys;
        }
    }

【C#】TreeView 的 CheckBox打勾後自動POST BACK


ASP.NET中的TreeView有ontreenodecheckchanged的事件,但當你在TreeView上打勾時,卻不會觸發Post Back的效果


查了一下,原來.Net會記住你目前TreeView的狀態,當有任何東西造成Post Back的時候(例如按按鈕),就會觸發ontreenodecheckchanged的事件


所以如果想要CheckBox點擊時能即時的Post Back就要做一些小加工

  1. 先加一個按鈕,並請隱藏起來

    這裡需要特別注意不能直接用Visible="false"將按鈕隱藏,否則ASP不會將這個按鈕真的Render出來。所以請用CSS的方式隱藏吧!!
  2. 透過JavaScript的方式(這邊利用JQuery撰寫),偵測當CheckBox被點擊時去觸發我們隱藏起來的Button,透過這個Button達到Post Back的效果



這樣就會進到ontreenodecheckchanged的事件

【SharePoint】確認Web或List是否有權限讀取


詳細可以參考這個網站

節錄摘要,


if (oWeb.DoesUserHavePermissions(SPBasePermissions.ViewPages))
{
      SPList oList = oWeb.Lists[ListName];
      if (oList.DoesUserHavePermissions(SPBasePermissions.ViewListItems))
      {
          // some smart code
      }
}

因為要先Get Web或是List的物件才能進行判斷,所以如果該使用者對該物件沒有權限,這樣寫可能會當掉,所以建議寫法如下

SPUser User = SPContext.Current.Web.CurrentUser; //先記錄目前使用者

SPSecurity.RunWithElevatedPrivileges(delegate {        //進行升權的動作
                        using (SPSite Site = new SPSite(SPContext.Current.Site.ID))
                        {
                            using (SPWeb Web = Site.OpenWeb(WebName))
                            {
                                //在將剛剛紀錄的使用者丟到Function進行權限的判斷
                                if(Web.DoesUserHavePermissions(User.LoginName,SPBasePermissions.ViewPages))
                                {
                                    SPList List = Web.GetList(URL);
                                    if(List.DoesUserHavePermissions(User, SPBasePermissions.ViewPages))
                                    {
                                        HavePermission = true;
                                    }
                                }
                             }
                        }
});
    

或是
//如果不把SPSecurity.CatchAccessDeniedException改回正常狀況,Sharepoint網站會直接返回無權限的頁面
//並停止執行接下來的程式
private bool CheckPermission(SPWeb _web) 
{
   Boolean catchException = SPSecurity.CatchAccessDeniedException;
   SPSecurity.CatchAccessDeniedException = false;
   try
   {
      if (_web.DoesUserHavePermissions(currentUser.LoginName, SPBasePermissions.ViewPages))
      {
         return true;
      }
      else 
      {
         return false;
      }
    }
    catch 
    {
         return false;
    }
    finally
    {
         //reset the flag to original value
         SPSecurity.CatchAccessDeniedException = catchException;
    }
}

2012年11月12日 星期一

【SharePoint】在LayOut底下的資料夾寫入txt的Log檔


我在佈署SharePoint專案時在LayOut資料夾底下放了一個Log的資料夾,打算在該資料夾寫txt的Log檔用,結構如下圖

首先要在Log資料夾裡下先隨便放個檔案,否則VS在佈署時發現該資料夾沒檔案就不會真的建那個該資料夾出來。
























以下程式是抓到佈署完之後該資料夾的實體位置,並以一天一檔案的方式寫Log檔







2012年11月1日 星期四

【SharePoint】 佈署方式


參考資料


透過命令提示字元佈署
  • stsadn 路徑
              C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\BIN
          
  • 部署
    • 加入Solution
                        stsadm -o addSolution –filename [xxxx.wsp]
                    
    • 部署Solution
                        stsadm -o deploysolution –name [xxxx.wsp] -immediate –url [SiteURL] -allowGacDeployment
                    
  • 移除
    • 解除Solution
      stsadm -o retractsolution –name [xxxx.wsp] -immediate -url [SiteURL]
    • 移除Solution
      stsadm -o deletesolution –name [xxxx.wsp]
  • 更新
    • 如果Solution已經在網站上使用,就可以使用下面一句命令就可以更新,不用先執行上面先解除再移除然後再重新部署
      stsadm -o upgradesolution –name [xxxx.wsp] –filename [xxxx.wsp] -immediate -allowgacdeployment

透過SharePoint管理介面更新佈署
  • 部署
    • 加入Solution
      Add-SPSolution C:\xxx.wsp
    • 安裝Solution
      Install-SPSolution -Identity xxx.wsp -WebApplication http://xxxx.com.tw -GACDeployment
  • 更新
    Update-SPSolution -Identity xxx.wsp -LiteralPath C:\xxx.wsp -GACDeployment
  • Restore
    restore-spsite -identity http://xxx.com.tw -path d:\xxx.bak -force

2012年10月28日 星期日

【SharePoint】 取清單的值


1.先開啟sharepoint site
2.開啟web
3.選擇清單
4.清單裡面item要撈出哪幾個欄位



=====================================================================

sharepoint在撈清單時,預設用使用者的權限去取得該清單的item

但有時候該清單需要更高的權限才能存取,這時候就要先做升權的動作,如紅框處



紫色框框處為清單的搜尋語法,但還在摸索中,先做個簡單的紀錄!!

2012年10月18日 星期四

【JavaScript】判斷檔案是否存在



最近用IE判斷某檔案是否存在,路徑分別有以下兩種情況
相對路徑 : %appdata%\Microsoft\Windows\Start Menu\\Programs\Accessories\Notepad.lnk
絕對路徑 : C:\xxx\xxxx\Microsoft\Windows\Start Menu\Programs\Accessories\Notepad.lnk

原本只是單純使用ActiveXObject('Scripting.FileSystemObject')FileExists來判斷該檔案是否存在

在絕對路徑下都很OK,但這個function無法判斷相對路徑,所以必須先做一個轉換為絕對路徑的動作
var objShell = new ActiveXObject("Wscript.Shell"); 

objShell.ExpandEnvironmentStrings("%appdata%\\Microsoft\\Windows\\StartMenu\\Programs\\Accessories\\Notepad.lnk");

再丟給FileExists來判斷檔案是否存在,即大功告成。

全部code
var objnav = navigator;
var OsVersion = objnav.appVersion;
var fso = new ActiveXObject('Scripting.FileSystemObject');
var objShell = new ActiveXObject("Wscript.Shell");
 
strfolderpath = objShell.ExpandEnvironmentStrings("%appdata%\\Microsoft\\Windows\\StartMenu\\Programs\\Accessories\\Notepad.lnk");
if (fso.FileExists(strfolderpath)){
   alert('絕對路徑有');
}
else{
   alert('絕對路徑沒有');   
}

2012年10月16日 星期二

VM上網設定


連結有詳細介紹!!   終於可以安心在VM裡面開發SharePoint了

Windows7中的VMWare網路設定
以下是摘錄
  • 首先開啟網路共用中心 > 變更介面卡設定 > 找到VMnet1然後記住它的名稱
  • 找到目前的連線(此圖為無線網路連線)> 右鍵點選內容 > 切到"共用"頁籤> 然後把共用都打勾並選擇剛剛那個VM的連線與他共享
  • 接著點選VMnet1右鍵 > 內容 > TCP/IPV4 >設定如下
  • 執行 VMWare 及虛擬系統,例如:Windows XP,開啟虛擬系統的「網蔎連線」,在「區域網路」上按滑鼠右鍵,選擇「內容」
  • 最後在 VMWare 的「VM \ setting」中將「Hardware \ Ethenet」設定為「Host-Only」

【SharePoint】安裝筆記


1.先安裝Window server 2008 R2

2.啟動Active Directory網域服務

3.啟動DC

4.新增兩名Domain的使用者  EX:sps_service , sps_admin


之後再將兩個帳號加到Builtin的administrator的成員之中



接下來的安裝都用sps_admin來做
5.安裝SQL Server 2008 R2
   將帳戶指定給sps_service


6.安裝SharePointService
   先點選安裝軟體先決條件

過程中如果有問題的話,可以參考提示另行下載元件安裝
元件表

7.正式安裝SharePoint
   選擇新的伺服器陣列 > 設定機器名稱 > 輸入使用者名稱與密碼

指定Port

之後再設定頂層網站就大功告成了!!

2012年10月15日 星期一

【JavaScript】showModalDialog運用


最近公司專案有使用到IE的showModalDialog,所以做一下筆記!!

叫用方式:
function openWindow(url) {
   var Feature = 'dialogWidth:850px;dialogHeight:600px;status:0;help:0;';
   var showModalObj = window.showModalDialog(url, window, Feature)
}

各項參數請參考MSDN文件:參數設定

我的是寫個function,如要使用時將url傳進來。其中第二個參數window是將這這個視窗傳遞給開啟的showModalDialog,之後方便showModalDialog叫用母視窗的function或是變數。


例如我在母視窗有個alertMe的function
function alertMe() {
   alert('我是母視窗的一個function');
}

我只要在showModalDialog視窗中使用 window.dialogArguments.alertMe(); ,就可以直接到母視窗的function。


另外showModalDialog無論是postback或是location到別的網址都會開啟新視窗,所以在<head>裡面加上
<head>
   <base target="_self" >
</head>
這樣目標就會是showModalDialog自己。



為了解決showModalDialog因為Cache的關係只有第一個會PostBack的問題,請加入以下的code在page_load事件,讓每次開啟modal dialog都會PostBack
if (!Page.IsPostBack) 
{
   //為了解決showModalDialog常常會讀到舊頁面的問題
   Page.Response.Expires = -1;
   Page.Response.AddHeader("Pragma", "no-cache");
   Page.Response.AddHeader("cache-control","no-store");
}

或是在Head裡面加上
    <meta http-equiv="Pragma" content="no-cache">
    <meta http-equiv="expires" content="-1"> 
    <meta http-equiv="cache-control" content="no-store">


showModalDialog回傳True或false給母頁面的方法
showModalDialog頁面寫以下Javascript
window.returnValue = false;

母頁面寫以下Javascript
if (window.showModalDialog(url, window, set))
{
   alert('true');
}
else
{
   alert('false');
}



showModalDialog回傳值的方式
showModalDialog頁面寫以下Javascript:
function GoReturnValue() {
   //宣告一個Object
   var ReturnObj = new Object();
   //給這個Object屬性值
   ReturnObj.codeValue = "i'am return value";
   //將這個Object回傳
   window.returnValue = ReturnObj;
   window.close();
}

母頁面取值方式:
var returnObj = window.showModalDialog(url, window, Feature);
//取得這個Object的屬性值,在這邊應該會得到"i'am return value"
alert(returnObj .codeValue);

2012年10月8日 星期一

【JQuery】ready 與 load的差別


節錄自
http://blog.miniasp.com/post/2010/07/24/jQuery-ready-vs-load-vs-window-onload-event.aspx


  • jQuery(document).ready(function() { … }) 《  或簡寫為 $(function() { … });  》
    • 當 document 物件下所有 DOM 物件都可以正確取得時,就會觸發 jQuery.ready() 註冊的 function,這時雖然後 <img src="…" /> 定義的圖片正在下載,但由於 <img> 這個 DOM 物件已經都 ready 了,所以 jQuery 並不會等圖片全部下載完畢才執行 ready 事件。
  • jQuery(window).load(function() { … })
    • 而使用 window 的 load 事件,卻是完全不同的行為,jQuery 裡的 window 的 load 事件與 JavaScript 裡的 window.onload 事件一模一樣,註冊在這裡面的事件都會等到整個視窗裡所有資源都已經全部下載後才會執行,例如該頁面有 100 張圖片就會等 100 圖片都下載完才會執行,其中也包括所有 iframe 子頁面的內容必須完整載入。

2012年10月7日 星期日

【C#】GridView補齊空白行


要將GridView每頁都顯示固定行數,例如每頁5筆而該頁卻只有三筆時要補兩行空白行

原本想從GridVeiew DataSource的DataTable著手

但DataTable.NewRow()會有內容schema的問題,所以查了一下網路上的方法


可以從DataBound事件下手,如下



2012年9月23日 星期日

2012年9月14日 星期五

【HTML】div 垂直置中


以下內容完全節錄自 http://blog.yam.com/hanasan/article/35806444 作者


本次要介紹的是CSS垂直置中(Vertical Align with css)的完整解決整理。
說實話這並不太容易,雖然不像水平置中 {margin:0 auto;} 那樣單純, 但仍有幾種方式可以作到,以下共有五種方式一一介紹。
每種使用方式各有其優、缺點,端看自己要置中的內容是「區塊」或是「文字」來取捨。

方法一

使用CSS table-cell屬性來完成,什麼是table-cell?簡單說就是針對一些html object附于它table的屬性(詳見此),如果曾經使用過table來排版的網頁開發者,應該知道td的既有屬性valign,古早以前根本不會有垂直置中的問題,因為td下個valign="middle"就行了。 而table-cell即是可以將div模擬成表格(table)的儲存格(td),讓原本不存在vertical-align的div可以使用。

Sample Code

HTML

<div id="wrap">
    <div id="cell">
        <div id="content">
            要被置中的內容
        </div>
    </div>
</div>

CSS

#wrap { display:table; }
#cell { display:table-cell; vertical-align:middle; }
優點:
  1. 因為是CSS2.1釋出的標準屬性,正規的解決方法。
  2. 被置中的內容增加後,垂直置中的block會自動調整。
缺點:
  1. 支援性不佳,IE8以上才支援(IE7以下不支援display:table語法)
  2. 太多巢狀標籤(有種回到過去table排版的fu)

方法二

此方法適用在定義了絕對定位(absolute)的div, 將其top設置為50%, 再設置與div高度一半的「負」值margin-top,意謂著使用本方法必須固定div的高度。

Sample Code

HTML

<div id="center">
    要被置中的內容
</div>

CSS

#center {
    position:absolute; height:400px; top:50%; margin-top:-200px; /* div高度的一半 */
}
優點:
  1. 程式碼簡短,且無需為了「垂直置中」的目的多寫巢狀標籤
  2. 所有browser都支援,泛用性高
缺點:
  1. div高度需固定,若是動態資料有可能超過的話需要加上overflow:scroll讓溢出的內容可以看見

方法三


在需要被垂直置中的div前放置另一個div,設置為height:50%,margin-bottom:-contentHeight(目標高度的負值)

Sample Code

HTML

<body>
    <div id="floater"></div>
    <div id="middle">
        要被置中的div
    </div>
</body>

CSS

html, body {
    margin:0; padding:0; height:100%;
}
#floater { float:left; height:50%; margin-bottom:-200px;
    width:1px; /* only for IE7 */
}
#middle {  clear:both; height:400px; position:relative; }
優點:
  1. 所有browser都支援(Note:IE7必須在#floater追加width:1px才work!)
  2. 當內容增加時,垂直置中的div不會被切掉,而是會自動出現scroll-bar
缺點:
  1. 沒甚麼缺點,真要說就是一樣高度得固定。另外若置中物件的父層是body, 即使視窗被USER拖曳拉小了,div也一樣會唯持置中(笑)

方法四

本法使用在同樣是絕對定位(absolute)的div上,固定高度,並定義top:0; bottom:0; 和廣為被應用的
{ margin:0 auto; }作div水平置中原理類似

Sample Code

HTML

<div id="middle">
    我要被置中啦~
</div>

CSS

#middle {
    position:absolute; width:70%; height:280px;
    top:0; bottom:0; left:0; right:0; margin:auto;
}
優點:
  1. 簡單
缺點:
  1. 不支援IE7(含)以下
  2. 如果容器不夠裝內文, 也不會有scrollbar自動出現...

方法五

此方法適用於「單行」文字的垂直置中(EX:要作英文網站大Slogan時), container除了設置高度之外,同時也將行距(line-height)設置與高度相等。

Sample Code

HTML

<div id="content">
    一行文字要被置中啦
</div>

CSS

#content { font-size:32px; text-align:center; height:150px; line-height:150px; }
優點:
  1. 簡單
  2. 所有browser都支援(even IE6!)
  3. 即使內容溢出也不會被切掉
缺點:
  1. 只有單行文字適合
  2. 若div寬度固定,一當有長文字爆行時會很醜,務必小心使用。
以上列出五種使用純CSS(不加js)達成div vertical align(垂直置中)的藥方,可以綜合搭配使用,也可視情況單獨使用...

2012年9月10日 星期一

2012年8月30日 星期四

【ASP】網頁更改web.config設定


讀取WebConfig AppSettings
   
   using System.Web.Configuration; //先Using

   WebConfigurationManager.AppSettings["Connection"]


改AppSetting
  Configuration myConfiguration = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~");
  myConfiguration.AppSettings.Settings["DSN"].Value = "abc"; //給你要設定的值
  myConfiguration.Save();

建議先用FileStream去讀取webConfig檔案,判斷是否可以讀寫,避免當掉。

2012年8月23日 星期四

【ASP】利用Global來達成固定時間就產生一次報表


客戶有個需求,需要每5分鐘、每一天、每一個月固定時間就產生特定的報表。

必須全自動化,所以不可能是透過人工登入到ASP網站後按XXX按鈕來產生報表,要解決這個問題就必須利用 Global.asax,只要IIS是啟動的情況下,且該網站的資源沒被回收的情況下就會固定執行Global。

System.Timers.Timer RegularTimer; //定時檢查黑名單計時器
System.Timers.Timer DailyReportTimer; //每日檢查 以黑名單產生報表
將要執行的內容放在 Application_Start裡面。


剛剛有提到,其實IIS會固定在網站的資源回收,這個可以在IIS的設定中去找回收時間,如果這個網站的資源被回收的話,Global就不會被執行,所以為了避免這個情況必須在Application_End事件裡寫下這段程式碼
void Application_End(object sender, EventArgs e) 
{
   //  在應用程式關閉時執行的程式碼
   System.Threading.Thread.Sleep(1000);
   string Url = "要呼叫的網頁Url";
   System.Net.HttpWebRequest wRequest = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(Url);
   System.Net.HttpWebResponse wResponse = (System.Net.HttpWebResponse)wRequest.GetResponse();
   System.IO.Stream stm = wResponse.GetResponseStream();
}

當IIS回收這個網站結束時,會觸發Global裡的Application_End,在裡面再次呼叫這個網站的隨便一個網頁,使得IIS在重新啟動它,這樣Global又會跑了!!

【ASP】UpdatePanel 與 JQuery


當Update Panel造成PostBack過後,會讓JQuery失效,大致的原因為DOM物件並沒有初始化,可以用以下的方式達成重新設定的目地

$(function () {
   SetJavaScript();
   Sys.WebForms.PageRequestManager.getInstance().add_endRequest(SetJavaScript);
});
function SetJavaScript()
{
   $("#btnAddEvent").click(function(){
      alert('123');
   });
}


將要初始化的內容包在一個function裡面,以上圖來說,將設定包在SetJavaScript()裡面

當Update Panel有更新時,會處發Sys.WebForms.PageRequestManager這段,他就會重新設定了!!

2012年8月15日 星期三

【ASP】防止Session Timeout


客戶的需求是除非登出,不然網站掛著要可以一直使用

也就是不能讓IIS判定你閒置過久將你time out掉

查了一下網路上分享的方法可以歸為兩大類

1.放個iframe連結到一個空的頁面,一段時間就refresh一次

2.用ajax的方式跟server要一個空網頁

但第二個方法我一直沒有式成功,所以採用第一個方法來解這個問題


先藏一個隱藏的iframe並連結到一個空的asp網頁


接著寫JavaScript來驅動他一段時間就refresh一次



這樣就解決摟

PS.IIS預設是閒置20分鐘就Time Out

2012年8月1日 星期三

【ASP】WebConfig設定強迫登入


ASP要強迫使用者登入後才能看到主頁面的話
可以在WebConfig裡面加上這段

登入網站時他會先判斷是否已經為登入狀態,如果為否則會導到wFrmLogin.aspx的頁面去並要求登入帳號密碼

如果要取消這項規定可以改成一下設定

2012年7月31日 星期二

【HTML】三個DIV並排,使中間的DIV自動填滿版面


如果有三個div,分別為left , middle,  right

而left與right的寬度是固定的,要依照不同的解析度將 middle 自動填滿剩餘的部分

做法如下


<div class='container'>
    <div class='right'>
        col3
    </div>
    <div class='left'>
        col1
    </div>
    <div class='middle'>
        col2
    </div>
</div>



.container {
    overflow: hidden;
}
.right {
    float: right;
    width: 100px;
}
.left {
    float: left;
    width: 100px;
}
.middle {
    margin: 0 100px;
}


特別注意div排放的順序, middle要擺在最後面一個

轉自http://stackoverflow.com/questions/7292021/3-columns-middle-one-with-flexible-width

2012年7月17日 星期二

【SQL】PWDENCRYPT 與 PWDCOMPARE (SQL謎樣的函數)


今天在公司認識了SQL中的這兩個函數,以下這個部落格有比較完整的資料可供參考

http://blog.miniasp.com/post/2008/12/SQL-Server-secret-PWDENCRYPT-and-PWDCOMPARE-function.aspx

簡單的說pwdencrypt是負責加密(變成binary的型態),而pwdcompare是負責比對
比較特別的地方是,就算是相同的字串進行加密,每次得到的加密結果都不相同。

2012年7月12日 星期四

【ASP】Response.End() 與 ASP按鈕click事件


今天幫同事處理一個檔案下載的問題,他是用LinkButton的click事件
在裡面判斷該下載哪個檔案,問題出在下載一次後所以按鈕事件都會失效
ASP中的Button與LinkButton之類的都是透過JavaScript來觸發PostBack

查了網路後發現有人也碰到相同的問題!!!
因為同事之後改用別的方法去處理下載,不給我測試了Q_Q

紀錄一下查到的solution 如果之後有碰到再來測試一下!!

http://social.msdn.microsoft.com/Forums/en-US/sharepointdevelopment/thread/107b2c17-07fe-4a15-ad81-dcb31e1e9c84/

2012年7月9日 星期一

2012年5月14日 星期一

【ASP】掛載JavaScript檔之ID問題


ASP搭配JQuery常常搭配ID的方式有三種方式
1.將控制項的ClientIDMode設定為static,這樣該控制項你設定甚麼ID他就是甚麼ID
2.依照ASP的規則預先拼湊出轉成HTML後的ID 例如 :ContentPlaceHoder_c01111_abc
3.另一種就是用<%= textbox1.ClientID %>

之前三種方式都使用過沒遇過什麼問題,直到我膝蓋中了一箭.....


以前的方法:


實驗結果,的確有用


但神奇的是如果把這段JavaScript移到獨立的JS檔,也就是用載入,就會失效

程式如下:
JS檔的程式碼原封不動如下:



結果我用alert('<%= TextBox1.ClientID %>')將這串印出來試試看
結果得到原封不動的"<%= TextBox1.ClientID %>"

然後將alert('<%= TextBox1.ClientID %>')移回到ASPX的檔案裡面即可正常的印出TextBox1的ID字樣。



看來<%= TextBox1.ClientID %>這個東西只能放在asp的檔案裏面才能使用,如果想用外掛JS檔的方式這招行不通


解決方案


改天研究出更好的方法再來更新!!!!

2012年4月7日 星期六

【SQL】 Case When Then 和 isNull的用法



ISNULL: 第一個參數如果取得的值為Null時,則用第二個參數當作其值


Case When Then: 以這個例子為例,如果OrderDetail.BookType抓到的值為'true'時,則傳回'電子檔',如果是'false'時,則傳回'書本',最後這個欄位名稱取名為'書本型態'

【C#】自訂控制項裡的button事件 如何讓上層的Form註冊


之前看了一篇文章,有提到如何實作,今天剛好把筆記補上

看標題可能有點難懂這篇在做什麼!?  先來解釋一下~

這是我做的控制項,按下按鈕後可以展開一個由CheckBox、Label、Button組成的小Item
然而動態的給該Item文字顏色之類的,只要寫屬性進去即可,但如果我要使用該控制項裡面的Button click事件該怎麼辦呢?

因為該組合出來的控制項雖然有click事件,卻不是我要的只有按下"+"號按鈕時才觸發的事件,原來可以透過委派來解決這個問題

委派大略來說就是訂閱者與發佈者,從這角度來看,該按鈕就是發佈者,而使用這個控制項的Form就是訂閱者


所以在控制項的類別裡寫下以下程式
C#版本
    //Button Click的事件是經由EventHandler來進行委派的
    //所以用該Handler註冊一個事件,我將該事件取名為Button_Click(這個是等等要給外面的Form註冊的)
    public event EventHandler Button_Click; 

    //在自己做的控制項裡面註冊該按鈕的Click事件
    this.btnDetail.Click += new EventHandler(btnDetail_Click);
    

    //將button_click事件轉出
    private void btnDetail_Click(object sender, EventArgs e)
    {

        //在該事件裡面寫下以下程式,簡單的說就是檢查自己做的事件有無訂閱者,如果有就將事件透過Invoke的方法轉發出去。
        if(Button_Click != null)
        {
            //利用Delegate轉出該Event給註冊於Button_Click的Event Handler
            Button_Click.Invoke(sender,e);
        }
    }

VB版
    '註冊給外面呼叫的事件
    Public Event Button_Click(ByVal sender As Object, ByVal e As EventArgs)
    Private Sub btnDetail_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnDetail.Click
         '用RaiserEvent進行委派
         RaiseEvent Button_Click(sender, e)
    End Sub
這樣使用這個控制項的From只要有註冊Button_Click事件就可以自訂該按鈕按下後的效果了

2012年3月31日 星期六

【JQuery】AJAX 非同步上傳圖片


相隔幾年回頭看這篇網誌,除了覺得寫得亂七八糟之外,原本用的套件也已經無法使用了。
最近剛好有寫到類似功能,所以重新改過一遍,並且用比較簡單的方式記錄下來~

上傳的檔案的套件選用 blueimp/jQuery-File-Upload ,然後做了 一些些客製的修改(因為文件有些地方不是很懂,所以只好自己刻了)

所以總共使用到的套件如下
JQuery  1.11.1版  : 位置
Bootstrap 3 : 位置
jQuery-File-Upload  : 位置


首先先載入必要的套件
    
    <script src="Scripts/jquery-1.11.1.min.js"></script>
    <script src="http://blueimp.github.io/jQuery-File-Upload/js/vendor/jquery.ui.widget.js"></script>
    <script src="http://blueimp.github.io/jQuery-File-Upload/js/jquery.iframe-transport.js"></script>
    <script src="http://blueimp.github.io/jQuery-File-Upload/js/jquery.fileupload.js"></script>

    <link href="Content/bootstrap.min.css" rel="stylesheet" />
    <link href="Content/jquery.fileupload.css" rel="stylesheet" />
    <link href="Content/jquery.fileupload-ui.css" rel="stylesheet" /> 



接著套上以下Html

<div id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="false">
     <div id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="false">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-body">
                    <span class="btn btn-success fileinput-button">
                        <span>選擇圖片</span>
                        <!-- The file input field used as target for the file upload widget -->
                        <input id="fileupload" type="file" name="images[]" multiple="">
                    </span>
                    <span class="btn btn-primary submit">
                        <span>開始上傳圖片</span>
                    </span>
                    <br />
                    <br />
                    <div id="progress" class="progress">
                        <div class="progress-bar progress-bar-success"></div>
                    </div>
                    <table role="presentation" class="table table-striped" id="presentation">
                        <tbody class="files"></tbody>
                    </table>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-default" data-dismiss="modal">關閉</button>
                </div>
            </div>
        </div>
    </div>


這時候應該可以看到這個畫面


但是選擇圖片後還是不會出現檔案在列表中,請加上以下JavaScript

   <script>
        $(function () {
            var filesList = []; //用來存放所選的圖片檔案Array

            $('#fileupload').fileupload({
                autoUpload: false,// 自動上傳False.
                url: 'xxx.com/UploadFileAPI', //上傳圖片的API位置
                dataType: 'json',
                add: function (e, data) { //選擇圖片後會跑入這個事件

                    //將圖片讀取出來並且組成Html塞到內容區塊
                    filesList.push(data.files[0]);
                    var reader = new FileReader();
                    reader.onload = function (e) {
                        $('#presentation > .files').append(
                            $(
                            '<tr class="template-upload fade in">' +
                                '<td><span class="preview"><img src="' + e.target.result + '" class="previewImg" /></span></td>' +
                                '<td><p class="name">' + data.files[0].name + '</p><strong class="error text-danger"></strong></td>' +
                                '<td><p class="size">' + (data.files[0].size / 1000) + 'k</p></td>' +
                                '<td><button class="btn btn-warning cancel imgCancel"><span>取消</span></button></td>' +
                            '</tr>'
                            )
                        );
                    }
                    reader.readAsDataURL(data.files[0]);
                },
                progressall: function (e, data) {
                    //控制上傳的時候會跑的進度Bar
                    var progress = parseInt(data.loaded / data.total * 100, 10);
                    $('#progress .progress-bar').css(
                        'width',
                        progress + '%'
                    );
                }
            });
        })
    </script>



圖片是跑出來了,但是預覽圖片太不受控制,加入CSS來規範它
.previewImg {width:80px;height:60px}


這樣看起來就正常多了。測試圖片為波,你在幹嘛? ,超可愛的貓咪


接下來的問題是按下取消鍵沒有功能,所以繼續寫取消按鈕的JavaScript
//圖片取消
$('body').on('click', '.imgCancel', function () {
   var target = $(this).parents('tr.template-upload'); //找出要取消的照片是第幾張
   filesList.splice(target.index(), 1);  //記得要把filesList中的圖片也移除掉
   target.remove();
});


接著是開始上傳按鈕的JavaScript

// submit 註冊 click 事件
            $('.submit').on('click', function (e) {
                e.preventDefault();
                //判斷filesList,有選圖片才送
                if (filesList.length > 0) {
                    $('#fileupload,.imgCancel,.submit').prop('disabled', true);

                    // fileupload api: send, 將 filesList 的檔案送至指定的 url.
                    $('#fileupload').fileupload('send', { files: filesList })
                        .success(function (result, textStatus, jqXHR) {
                            //呼叫成功Call Back的地方
                            console.log(result);
                        })
                        .error(function (jqXHR, textStatus, errorThrown) {
                            console.log(jqXHR.responseText);
                        })
                        .complete(function (result, textStatus, jqXHR) {
                            //傳送完成後,讓Submit按鈕重新開啟
                            $('#fileupload,.submit').prop('disabled', false);
                            filesList.length = [];
                        });
                }
            });



後端接前端POST過來的API,這邊是用ASP MVC4,處理完後就搞定了!!

        /// <summary>
        /// 上傳Banner圖片
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public ActionResult UploadBannerPicture()
        {
            var picNames = new List<string>();
            //HttpContext.Request.Files,可以接到前端傳來的File
            if (HttpContext.Request.Files == null || HttpContext.Request.Files.Count == 0)
                return Json(new { filename = picNames });

            var fileList = new List<HttpPostedFileBase>();

            for (int i = 0; i < HttpContext.Request.Files.Count; i++)
            {
                //自己寫的,Check圖片的格式
                if (PictureFactory.CheckPictureFile(HttpContext.Request.Files[i].InputStream))
                    fileList.Add(HttpContext.Request.Files[i]);
            }
             
            //儲存圖片.....
            //.............

            //儲存完後回傳Json結果,讓前端去做後續處理    
            return Json(new { filename = picNames });
        }

2012年3月28日 星期三

【ASP】filestream "拒絕存取路徑"的問題


今天寫了一個AJAX程式透過泛型處理常式(ashx)來上傳圖片,不料卡在這行

他一直跳到Catch跟我說沒有讀取的權限,在網路上查了一下,只要加上短短的一句就可以解決了!!
不用為了這個還特地跑去開寫入的權限(為什麼讀取需要寫入的權限我也不懂...)



2012年3月25日 星期日

【SQL】預存程序與ASP的應用


SQL的預存程序建立方式如下

其中紅線框起的地方是這個預存程序執行需要的參數



在SQL Manager要執行預存程序的方法




在ASP裡要執行這個預存程序,寫法如下