2014年2月6日 星期四

Bootstrap v3.1.0範例

最近很夯的東西
可以幫助程式設計師在沒有美編時也能做出美美的網站
官網
懶的每次都寫
所以先包好直接copy用
內含
modernizr-2.6.2.js
jquery-1.10.2.js
bootstrap.js
bootstrap-select.js
respond.js

點我下載

2013年12月30日 星期一

Asp.net MVC NuGet安裝指定套件的版本(17)

VS有個很強的功能就是NuGet相信很多人都知了就不再多說
至於沒用過的可試試,只要在專案上按下右鍵如下圖及可搜尋及安裝

但像jQuery有很多版本確不想要安裝到最新的版本那怎麼辦?
jquery點選下面的版本
會有一行 PM > Install-Package jQuery -Version 1.10.2
到VS > 工具 > 程式庫套件管理員 >套件管理主控台 > 點一下就會出現主控台視窗 將剛的那一樣貼上執行即可

2013年12月22日 星期日

Asp.net jQuery+DropDownList連動後出現System.Web.HttpUnhandledException

這其實只是不了解jquery及asp.net postback的問題
有兩個DropDownList,Master及Detail
下拉Master連動Detail一般來寫程式碼都會如下
 $(function () {
    $("#<%= Master.ClientID%>").change(function () {
            var q = $("#<%= Master.ClientID%>").val();
                $.ajax({
                    url: '/get.ashx',
                    type: 'post',
                    async: true,
                    data: { q: q },
                    success: function (data) {
                        $('#<%= Detail.ClientID%>').empty();
                        var myarray = $.parseJSON(data);
                        $.each(myarray, function (i, item) {
                            var option = "<option value='" + myarray[i].value + "'>" + myarray[i].txt + "</option>";
                            $('#<%= Detail.ClientID%>').append(option);
                        });
                    }
                });
            });
  });
上面程式碼看似無誤,但在PostBack後就會出現System.Web.HttpUnhandledException
因為PostBack後會產生畫面
放在$(function (){});裡面又會跑一次但程式而此時就會造成錯誤
所以必需將select change放於jquery function外
 $(function () {
    
  });

$("#<%= Master.ClientID%>").change(function () {
            var q = $("#<%= Master.ClientID%>").val();
                $.ajax({
                    url: '/get.ashx',
                    type: 'post',
                    async: true,
                    data: { q: q },
                    success: function (data) {
                        $('#<%= Detail.ClientID%>').empty();
                        var myarray = $.parseJSON(data);
                        $.each(myarray, function (i, item) {
                            var option = "<option value='" + myarray[i].value + "'>" + myarray[i].txt + "</option>";
                            $('#<%= Detail.ClientID%>').append(option);
                        });
                    }
                });
            });

2013年12月18日 星期三

Asp.net 系統收到多個不同的 Content-Disposition 標頭。我們不允許這種情形,這是為了避免遭到 HTTP 回應分割攻擊。

今天使用者遇到了這個問題
系統收到多個不同的 Content-Disposition 標頭。我們不允許這種情形,這是為了避免遭到 HTTP 回應分割攻擊。
看了一下程式
 Response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}", mFileName));
 Response.AddHeader("Content-Disposition", string.Format("attachment; filename=\"{0}\"", mFileName));
多加了分雙引號這樣輸出的標頭才會指定檔名是什麼減少攻擊

2013年11月25日 星期一

IIS 回收時間(IIS Session Time Out)

很難得的遇到一次User全部被系統踢出去的經驗
所以判斷是IIS自己踢的
找了一下設定在
IIS > 應用程式集區 > 集區名稱上右鍵 > 進階設定
如圖

固定時間間隔(分鐘):預設是1740改成0就不會回收了

2013年11月17日 星期日

Javascript 秒數轉時分秒

最近常在網頁上用到
尤其是撥html5 video
   function formatSecond(secs) {          
            var hr = Math.floor(secs / 3600);
            var min = Math.floor((secs - (hr * 3600)) / 60);
            var sec = parseInt( secs - (hr * 3600) - (min * 60));

            while (min.length < 2) { min = '0' + min; }
            while (sec.length < 2) { sec = '0' + sec; }
            if (hr) hr += ':';
            return hr + min + ':' + sec;

        }
參考網址 點我

2013年11月12日 星期二

Asp.net MVC 必裝NuGet套件Elmah(16)

先廢話一下
今天不是實作了,完成前面幾項功能其實就差不多可以做出一個基本網站了
但這樣還不夠尤其實是錯誤訊息相當重要
因為程式總是會有例外
所以必需靠這些訊息來判斷那裡有問

安裝NuGet套件方式 點我前往
相關教學 點我前往
點我前往
其實就幾個重點
1.elmah.mvc.route最好設定不要使用預設
2.如果開啟遠端如下,一定要設定elmah.mvc.requiresAuthentication
  <elmah>
    <security allowRemoteAccess="1" />
  </elmah>
3.以下是幾個設定在相關教學裡有保哥說的很詳細
  <appSettings>   
     <add key="elmah.mvc.disableHandler" value="false" />
    <add key="elmah.mvc.disableHandleErrorFilter" value="false" />
    <add key="elmah.mvc.requiresAuthentication" value="true" />
    <add key="elmah.mvc.allowedRoles" value="*" />
    <add key="elmah.mvc.route" value="errorelmah" />
</appSettings>
參考網址
點我前往
點我前往

2013年11月9日 星期六

Asp.net MVC 實作抓最大排序及繫結的方法(15)

先廢話一下
其實很簡單但是有時會無法繫結
Controller部份先
//抓最大值
int Sort =  (from u in db.TabContent 
  where u.TabID==tabid
  select u.Sort).DefaultIfEmpty().Max(x => x == null ? 0 : x);
ViewBag.Sort = Sort + 1;
以上這部份很簡單沒問題吧
        <div class="form-group">
            @Html.LabelFor(model => model.Sort, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.TextBoxFor(model => model.Sort)
                @Html.ValidationMessageFor(model => model.Sort)
            </div>
        </div>
程式碼自動產生會這樣
但如何修改成能抓ViewBag
        <div class="form-group">
            @Html.LabelFor(model => model.Sort, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.TextBox("Sort",null, new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.Sort)
            </div>
        </div>
改成用弱型別是一個方法記得"Sort"這樣就能抓到ViewBag了
而且最好以欄位名稱命名
這樣在Model Binding時就能抓到值喔
不然會抓不到資料有興趣可以試試 參考網址

2013年11月4日 星期一

Asp.net MVC 實作jQuery+Html.DropDownList更換頁面資料(14)

先廢話一下
這功能蠻實用的原本還想說用AjaxBeginForm但不知該如何寫
雖然寫出來了但應該還有許多可以地方可以加強
Controller部份先抓產生下拉選單的資料
        public ActionResult Index( )
        {
            ViewBag.TabData = new SelectList(db.Tab, "TabID", "TabName"); //產生下拉選單
            return View();
        }
View的部份也放一個@Html.DropDownList接收下拉選單
也放一個DIV來準備給jQuery用
@Html.DropDownList("TabData", null, null, new { id = "ddTabData" })
然後產原本產生的Index裡的Table另外開一個_List.schtml裡
所以這時畫面應該只剩一個下拉選單
我們要讓下拉後變更整個Table裡的資料
怎麼做當然就是去呼叫剛的頁面
要動態更新DOM我只會jQuery哈
  
        $(function () {     
            $("#ddTabData").change(function () {
                var selectedItem = $("#ddTabData").val();
                $.ajax({
                    cache: false,
                    type: "GET",
                    url: "@(Url.Action("GetList", "TabContent", null))",
                    data: { "tid": selectedItem },
                    success: function (data) {
                        $("#Content").html(data);
                    },
                    error: function (xhr, ajaxOptions, thrownError) {
                        alert('讀取資料失敗.');
                    }
                });
            });          
        });
    
去呼叫@(Url.Action("GetList", "TabContent", null))

  public ActionResult GetList(int tid = 1)
        {
            var tabcontent = db.TabContent.Where(u => u.TabID == tid).Include(t => t.Account).Include(t => t.Account1).Include(t => t.Tab);
            return View("_List",tabcontent.ToList() );
        }
這樣就會回傳一整個Table回來
但_List.cshtml裡除了原本宣告model要放
@{    
    if (IsAjax)
    {
        Layout = null;
    }    
}
上面這句也要加,不加差在那邊各位可以自己測試!!

2013年11月2日 星期六

Asp.net MVC 實作AutoMapper後加上PagedList(13)

先廢話一下
今天終於將MVC課程上完了
接下來就要多練習
上篇文章提到AutoMapper可自動轉型
但試了很久就是沒法轉成PagedList
還好運氣不錯找到一篇文章>
public ActionResult Index()
{
	Mapper.CreateMap<Account, AccountMV>(); 
        var OrderList = db.Account.OrderBy(o => o.AccountID);//設定OrderBy List
        var PagedList = OrderList.ToPagedList(p, 2);//分頁的 List
        var viewmodel = Mapper.Map<IEnumerable<Account>, IEnumerable<AccountMV>>(PagedList.ToArray()); // 分頁列表轉換成ViewModel
        var query = new StaticPagedList<AccountMV>(viewmodel, PagedList.GetMetaData()); // reconsitute a new IPagedList containing the viewmodels
        return View(query);       
}
說真的我還真看不太懂最後一行那句
但這樣在View中是完全不需要更改的
寫到現在這樣CRUD最底層都差不多寫好了
簡單的專案也差不多快完成了
參考網址
PagedList

2013年11月1日 星期五

Asp.net MVC 實作AutoMapper Mapping Model and ViewModel(12)

先廢話一下
第一次寫MVC檢視一下程式碼
發覺定義了太多ViewModel
只要新增一個欄位後View Controller Model居然都需要改
天阿這一定不會是我想要的
相信寫MVC的人覺對不會想發生這種問題
Google搜尋後發覺有一個好的套件
AutoMapper在NuGet裡搜尋就能找到安裝
來看一下原本的程式碼
public ActionResult Index()
{
 var query = from u in db.Account
                    select new AccountVM
                    {
                        AccountID = u.AccountID,
                        AccountName = u.AccountName,
                        IsUsed = u.IsUsed,
                        LoginIP = u.LoginIP,
                        LoginDate = u.LoginDate,
                        Name = u.Name,
                        Email = u.Email
                    };

         return View(query);
}
看以上程式碼只要加一個欄位每次都要跑來修改
唉~對於最內部系統的人最痛苦的事就是新增欄位了
來看一下使用AutoMapper
public ActionResult Index()
{
        Mapper.CreateMap<Account, AccountVM>();
        List<Account> account = db.Account.ToList();
        List< AccountVM> query = Mapper.Map<  List< Account>,List< AccountVM>>(account);   
        return View(query);
}
這樣不管怎麼增加欄位都不需要在Controller修改了
只是目前不知會不會有什麼Bug 參考網址
點我

Asp.net MVC 實作DropDownList繫結資料庫selected(11)

先廢話一下
DropDownList很簡單阿
WebForm用selectvalue=xxx就好
但MVC的DropDownList讓我研究了一早上

大部份在網路上找的都是建立或者連動DropDownList
可能是我搜尋功力差找不到繫結資料庫又能Select的方法
自己想了一個很瞎的方式
就是自己判斷抓出來的值跟DropDownList有沒有一樣
然後把Select變True
只是不知這樣是否為最佳的寫法
以下是View程式碼
@{                    
 List<SelectListItem> list = (List<SelectListItem>)ViewBag.TabColumnName;
 foreach (var s in list )
 {
     if (item.TabColumnName.Equals(s.Value))
  {
   s.Selected = true;
  }
  else
  {
   s.Selected = false;
  }            
 }
}              
@Html.DropDownListFor(modelItem => item.TabColumnName, list)  
Controller如下
ViewBag.TabColumnName =TabColumnVM.getTabColumnName(); 

2013年10月31日 星期四

Asp.net MVC 實作TempData應用自訂Error(10)

先廢話一下
大部份都會設計刪Master時Detail也順便刪
依需求所以做個不一樣的
如果Detail是有資料時就提示不能刪除Master
這樣好像讓資料更安全點
使用TempData來紀錄錯誤的訊息
為何用TempData因為他只會被使用一次
所以在post錯誤時傳給Get一次顯示
  public ActionResult Delete(short? id)
        {            
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
     //重點在這裡接收後顯示錯誤
            if (TempData["CustomError"] != null)
            {
                ModelState.AddModelError(string.Empty, TempData["CustomError"].ToString());
            }

            //Account account = db.Account.Find(id);
            var query = from u in db.Tab where u.TabID == id;

            if (query == null)
            {
                return HttpNotFound();
            }
            return View(query);
        }

        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(short? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }

            string Sql = " TabID == @0";
            var query1 = (from u in db.TabColumn.Where(Sql, id)
                          select u).ToList();
            if (query1.Count() > 0)
            {               
  //有錯時丟給Get顯示
                TempData["CustomError"] = "頁籤內有欄位所以不可刪除";
                return RedirectToAction("Delete",null, id);
            }

            Tab query = db.Tab.Find(id);
            db.Tab.Remove(query);
            db.SaveChanges();
            return RedirectToAction("Index");
        }
在View裡記得加以下才會顯喔
@Html.ValidationSummary(true)
參考網址

2013年10月30日 星期三

Asp.net MVC 實作TextBoxFor DataFormat(9)

先廢話一下
多實作多健康
一般會在Model裡設定DataFormat
[DisplayName("時間")]
[DataType(DataType.Date), DisplayFormat(DataFormatString = "{0:yyyy-MM-dd HH:mm:ss}", ApplyFormatInEditMode = false)]
public Nullable pDate { get; set; }
以上在list用DisplayFor都沒什麼問題
但TextBoxFor時如果MS-SQL是中文版的還是會出現上午、下午這種字眼當然驗證就不會過了
改成如下就能正常顯示yyyy-MM-dd HH:mm:ss
@Html.TextBoxFor(model => model.LoginDate, "{0:yyyy-MM-dd HH:mm:ss}", new { @class = "form-control", @readonly = "readonly" })
參考網址
點我

Asp.net MVC 實作使用TryUpdateModel更新資料(8)

先廢話一下
最近真的越寫MVC越上癮了
雖然因為很不熟一直卡
但是做出來的成就感特別好
有些東西做出來但是還是有些詳細的原理還需了解

終於做到需要開始CRUD了
首先針對會員資料做更動
最先遇到的是修改欄位後有些欄位不更新
找了兩篇相當好的文章 點我 點我
使用TryUpdateModel有10個多型能使用
重點再於第四個參數
為不更新的欄位名稱
沒輸入密碼時不更新>
  [HttpPost]
        [ValidateAntiForgeryToken]
       
        public ActionResult Edit(int Id, AccountEdit Form)
        {
            if (ModelState.IsValid)
            {              
                Account query = db.Account.Find(Id);               
                List<string> list = new List<string>();

                //  沒打 是空時 時不更新
                if (Form.Password == null || Form.Password.ToString().Equals(""))
                {
                    list.Add("Password");
                }
           
                if (TryUpdateModel(query,"",null,list.ToArray()))
                {
                    try
                    {
                        // 有打時 不是空 這段必需要寫在TryUpdateModel
                        if (Form.Password != null && !Form.Password.ToString().Equals(""))
                        {                            
                            query.Password =  PublicFunction.EncodeStringMD5(Form.Password); 
                        }                      

                        db.SaveChanges();
                    }
                    catch (Exception ex)
                    {
                        string e = ex.Message.ToString();
                        throw;
                    }
                   
                    return RedirectToAction("Index");
                }
                return View(query);
            }
            return View(Form);          
        }
       
有個特別的地方就是要輸入時才更新密碼部份
原本寫在TryUpdateModel外面感謝保哥指導
"TryUpdateModel會蓋掉 model的資料"
"因為他在這時後才做 Model Binding"
所以要寫在TryUpdateModel裡面
參考網址
點我
點我
微軟官方

2013年10月29日 星期二

Asp.net MVC 實作一個View多個Model(7)

先廢話一下
這功能看似簡單
但不知如何架構跟下語法可能會寫不出來
先在ViewModels裡建一個Class裡面有三個IEnumerable
public class TabContainerVM
    public class TabContainerVM
    {
        public IEnumerable tab { get; set; }
        public IEnumerable tabcolumn { get; set; }
        public IEnumerable tabrow { get; set; }
    }
在Controller裡把資料自行加入到model裡後回傳
>
  public ActionResult TabContainer()
        {
            var tab = from u in db.Tab                      
                      select u;

            var tabcolumn = from u in db.TabColumn
                            select u;

            var tabrow = from u in db.TabRow
                         select u;

            var model = new TabContainerVM
            {
                tab = tab,
                tabcolumn = tabcolumn,
                tabrow = tabrow
            };

            return PartialView("_TabContainer",model);
        }
view的話就能使用
@model  ViewModels.TabContainerVM

<div>
@foreach (var tab in Model.tab)
{
 <ul>
 @foreach (var tab in Model.tabcolumn )
 {
  //do something
  <li></li>
 }
 </ul>
}
</div>
參考網址 點我

2013年10月27日 星期日

Google 分析網頁效能工具

Google 分析網頁效能工具
剛忽然逛到真的需要記一下

Asp.net MVC 實作RenderBody和RenderSection(6)

先廢話一下
MVC好像越來越有趣了
如果個人邏輯相當好的話
可以在View中發揮的彈性很大
因為MVC網頁一種個感覺就很像在挖洞
可以到處填補彈性的確比WebFrom來的好
我想RenderBody和RenderSection的範例在新增一個專案後就會有了
RenderBody搭配一個_Layout所以一個_Layout只會有一個RenderBody
只要將頁面的_Layout路徑設定即能套用
  @RenderBody()
RenderSection在_Layout裡可以有許多的RenderSection
但切記是_Layout裡而不是在一般頁面裡喔
如果直接在一般頁面裡他會跳出以下錯誤
無法直接要求檔案 "~/Views/Home/Index.cshtml",因為它會呼叫 "RenderSection" 方法。

_Layout裡
required為true表示您只要是套這個_Layout的頁面都必需要又head的section不然會出錯這相當重要
  @RenderSection("head",required: false)
一般頁面
@section head{
//你的程式碼
}

2013-10-27補充
我做了一個測試在_Layout裡設定@RenderSection("head",required: false)
再將/Home/Index裡在呼叫一個Partial
而Partial裡加入
 @section head{
                
        }
在執行後Partial裡的程式碼完全不會顯示
所以Partial裡寫@section 是沒用的僅供參考摟!!

2013年10月26日 星期六

Asp.net MVC 實作登出及驗證(5)

先廢話一下
登入登出看似簡單但有許多需要注意的小地方
參考了很多網站才實作出來
上次做到Asp.net MVC 實作登入驗證(1)
當然要有驗證是否登入跟登出
找了許多站終於結合出比較有效的程式碼
驗證是否已登入,程式碼不長但很實用
if ( User.Identity.IsAuthenticated)
{
  //這邊是有驗證過已登入
}
如果是一整個Controller都需要驗證可加[Authorize]在Class上
如果整個Controller裡有不需驗證的可加[AllowAnonymous]
    [Authorize]
    public class HomeController : Controller
    {       
        [AllowAnonymous]
        public ActionResult Index()
        {
            ViewBag.Title = PublicFunction.WebSiteName; 
            return View();
        }

        public ActionResult Create()
        {
            return View();
        }
     
    }
以下是登出的完整程式碼
 [HttpPost]
        [ValidateAntiForgeryToken]     
        public ActionResult Logout()
        {
            FormsAuthentication.SignOut();
            Session.Abandon();

            // clear authentication cookie
            HttpCookie cookie1 = new HttpCookie(FormsAuthentication.FormsCookieName, "");
            cookie1.Expires = DateTime.Now.AddYears(-1);
            Response.Cookies.Add(cookie1);

            // clear session cookie (not necessary for your current problem but i would recommend you do it anyway)
            HttpCookie cookie2 = new HttpCookie("ASP.NET_SessionId", "");
            cookie2.Expires = DateTime.Now.AddYears(-1);
            Response.Cookies.Add(cookie2);

            //FormsAuthentication.RedirectToLoginPage(); 
            return RedirectToAction("Index", "Home", null);
        }

參考網站
登出實作
Session.RemoveAll() 及Session.Abandon() 的差別