一、新增MVC專案
題外話: 作者一開始並未勾選Web API, 結果使用Web API發生無法預期錯誤,只好建立新的專案,重練一次!
PS:注意 新建專案勾選web api和新增單元測試
測試單元是一個很有趣的議題,不過不在這次討論範圍喔~
一、建立版型
透過Bootstrap 進行佈景主題,許多文章也對此議題多做說明,我就不再多做說明
<body >
<header>
<div class="content-wrapper">
<div class="float-left">
<p class="site-title"> @Html.ActionLink( "your
logo here", "Index" , "Home") </p>
</div>
<div class="float-right">
<nav>
<ul id="menu">
<li> @Html.ActionLink( "新增", "Index" , "Home") </li>
<li> @Html.ActionLink( "About", "About" , "Home") </li>
<li> @Html.ActionLink( "Contact", "Contact" , "Home") </li>
</ul>
</nav>
</div>
</div>
</header>
<div id="body">
@RenderSection("featured", required: false)
<section class="content-wrapper
main-content clear-fix">
@RenderBody()
</section>
</div>
<footer>
<div class="content-wrapper">
<div class="float-left">
<p> © @DateTime.Now.Year - My
Telerik MVC Application </p>
</div>
</div>
</footer>
</body >
|
二、建立首頁
作者有使用Kendo UI的第三方套件,順便來看看如何運用在MVC的架構上
@model :
MVC架構中的Model 是實體資料庫的物件,透過@model 可直接把資料顯示在畫面上, 例如 @Html.DropDownListFor(m
=> m.targetType, Model.targetTypeValues) 使用到messageCenter.Models.entityMessage 的 targetTypeValues 值
Html.BeginForm("Index", "Home", FormMethod.Post)
如同早期語法<form
method=’post’ action=’Home/index’> ,按下Submit
後轉址 Home/Index
Html.Kendo().DateTimePickerFor: 選擇日期或時間的下拉式列表
.value(): 設定預設值
@Html.Kendo().EditorFor : 強大文字編輯方塊
設定預設值: .value()
|
上傳圖片路徑:
ImageBrowser(imageBrowser
=> imageBrowser
.Image("~/Content/UserFiles/Images/{0}")
.Read("Read", "ImageBrowser")
.Create("Create", "ImageBrowser")
.Destroy("Destroy", "ImageBrowser")
.Upload("Upload", "ImageBrowser")
.Thumbnail("Thumbnail", "ImageBrowser"))
|
編輯文字方塊的功能
.Tools(tools => tools
.Clear() // 清空
.Bold().Italic().Underline().Strikethrough() // 粗體,鈄體,…
.JustifyLeft().JustifyCenter().JustifyRight().JustifyFull() //字左,字中…
.InsertUnorderedList().InsertOrderedList()
.Outdent().Indent()
.CreateLink().Unlink()
.InsertImage() //插入圖片
.InsertFile()
.SubScript()
.SuperScript()
.TableEditing()
.ViewHtml() //檢示html 語法
.Formatting()
.CleanFormatting()
.FontName()
.FontSize()
.FontColor().BackColor()
)
|
@(Html.Kendo().Window() : 彈跳視窗
.Name("window")
.Title("Rams's Ten Principles of Good Design")
.Content("loading user info...")
.LoadContentFrom("DetailPage", "Home") //讀取頁面
.Iframe(true) //是否IFrame
.Draggable() //是否拖移視窗
.Resizable() //改變大小
.Width(800).Height(200) //視窗大小
|
各位有注意到@(Html.Kendo().DateTimePickerFor(m=>m.validateDatetime)
的語法,是設定model的欄位和view 之間的繫結, 資料post送到後端,就直接對應物件的屬性,十分的彈性。
|
@model messageCenter.Models.entityMessage
@using (Html.BeginForm("Index", "Home", FormMethod.Post))
{
<div class="body-content">
<label>
有效日期
</label>
<div id='to-do'>
@(Html.Kendo().DateTimePickerFor(m=>m.validateDatetime)
.Value(DateTime.Now)
)
</div>
<div class="form-group">
<label>訊息名稱 @Html.ValidationMessageFor(model => model.message)</label>
@Html.Kendo().EditorFor(m =>
m.message).HtmlAttributes(new
{
style = "min-width:100%;width: 740px;height:440px"
}).Deferred(false).ImageBrowser(imageBrowser => imageBrowser
.Image("~/Content/UserFiles/Images/{0}")
.Read("Read", "ImageBrowser")
.Create("Create", "ImageBrowser")
.Destroy("Destroy", "ImageBrowser")
.Upload("Upload", "ImageBrowser")
.Thumbnail("Thumbnail", "ImageBrowser")).Tools(tools
=> tools
.Clear()
.Bold().Italic().Underline().Strikethrough()
.JustifyLeft().JustifyCenter().JustifyRight().JustifyFull()
.InsertUnorderedList().InsertOrderedList()
.Outdent().Indent()
.CreateLink().Unlink()
.InsertImage()
.InsertFile()
.SubScript()
.SuperScript()
.TableEditing()
.ViewHtml()
.Formatting()
.CleanFormatting()
.FontName()
.FontSize()
.FontColor().BackColor()
)
</div>
<p></p>
<div class="form-group">
<label>
發佈類別
@Html.DropDownListFor(m => m.targetType,
Model.targetTypeValues)
</label>
</div>
<div class="form-group">
<label>
發佈對象
@Html.TextBoxFor(m => Model.targetUser)
<a href="javascript:void(0)" id="hyperlinkPage">
</a>
</label>
</div>
@(Html.Kendo().Window()
.Name("window")
.Title("Rams's Ten Principles of Good Design")
.Content("loading user info...")
.LoadContentFrom("DetailPage", "Home")
.Iframe(true)
.Draggable()
.Resizable()
.Width(800).Height(200)
)
<button type="submit" class="btn btn-success" id="btnAdd">新增</button>
</div>
}
|
三、建立controller
Kendo UI 的EditorFor 上傳圖片的功能,需要在Controller 新增 ImageBrowserController 類別,以下是上傳圖片的後端程式
public class ImageBrowserController : EditorImageBrowserController
{
private const string contentFolderRoot = "~/Content/";
private const string prettyName = "Images/";
private static readonly string[] foldersToCopy = new[] { "~/Content/shared/" };
/// <summary>
/// Gets the base paths from which content will be served.
/// </summary>
public override string ContentPath
{
get
{
return CreateUserFolder();
}
}
private string CreateUserFolder()
{
var virtualPath = Path.Combine(contentFolderRoot, "UserFiles", prettyName);
var path = Server.MapPath(virtualPath);
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
foreach (var
sourceFolder in foldersToCopy)
{
CopyFolder(Server.MapPath(sourceFolder), path);
}
}
return virtualPath;
}
private void CopyFolder(string source, string
destination)
{
if (!Directory.Exists(destination))
{
Directory.CreateDirectory(destination);
}
foreach (var file in Directory.EnumerateFiles(source))
{
var dest = Path.Combine(destination,
Path.GetFileName(file));
System.IO.File.Copy(file, dest);
}
foreach (var
folder in Directory.EnumerateDirectories(source))
{
var dest = Path.Combine(destination,
Path.GetFileName(folder));
CopyFolder(folder,
dest);
}
}
|
要瞭解Controller
的運作模式,早期web form 把view的事件視為後端的方法,然而在MVC中完全脫離這種模式,改以APP_Start\ RouteConfig.cs註冊的路由表,把資料送到對應的view
透過http呼叫的協定(get,post,
delete,put),來決定Action ,所以當按下確定送出submit,呼叫與view對應的Action,而且表頭有[HttpPost]
[HttpPost]
public ActionResult Index(entityMessage entityMessageObj)
{
}
|
範例:
網址: http://localhost:50135/Home/index
按下新增之後,會對應到有HttpPost的index的Action,此Action負責呼叫資料層的物件,呼叫Index(entityMessage entityMessageObj) Action。
public class HomeController : Controller
{
entityMessage entityMessageModel = new entityMessage();
public ActionResult
Index()
{
ViewBag.Message = "";
return View(entityMessageModel);
}
[HttpPost]
public ActionResult
Index(entityMessage
entityMessageObj)
{
if (ModelState.IsValid)
{
ViewBag.Message = "";
//轉成html語法
entityMessageObj.message = HttpUtility.HtmlDecode(entityMessageObj.message); entityMessageObj.add(); //儲存父表單和子表單
return RedirectToAction("About");
}
else
{
return View(entityMessageModel);
}
}
|
四、建立Ajax 網頁
Ajax 網頁的運作已經非常普遍,所以此案例中,將示範如何透過controller 回傳Json格式的資料給kendo UI,達到AJAX 的應用。
前端Script 使用JQuery 語法
$("#hyperlinkPage").html("<img src='\Images/detailForm.png'
id='imageDeatailPageIcon' />");
$("#hyperlinkPage")
.bind("click", function () {
$("#window").data("kendoWindow").open(); //彈出視窗
var wnd = $("#window").data("kendoWindow");
if ($("#targetType").val() == 1) {
//顯示欄位
var columns = [{ width: 30 },
{
field: "索引編號" },
{
field: "客戶名稱" },
{
field: "客戶地址" },
{
field: "客戶版本" },
{
field: "客戶合約等級" },
{
field: "郵遞區號" },
];
showGrid("\Home/listAllCustomers",
columns );
}
});
function showGrid( url, columns)
{
columns[0].template = "<input type='checkbox' id='ck_selected' class='checkbox' />";
var wnd = $("#window").data("kendoWindow");
wnd.content("<center><table id='detail_table_header'><div
id='grid'></div></table></center>");
var dataSource = new
kendo.data.DataSource({
transport: {
read: {
url:url, //取得對應Controler 的ACTION傳回資料
dataType: "json"
},
},
pageSize: 20, //此部份用分頁,每20筆1頁
schema: {
//此部分取回JSON資料,切注意,如無法取出資料, 確認JSON的格式 {Data:
[({object1},{object2})]} ,請依實際情況作調整
data: "Data",
total: "Total"
}
});
$("#grid").kendoGrid({
dataSource:
dataSource, //取得JSON
height: 550,
dataBound:
onDataBound,
groupable: true,
sortable: true,
pageable: {
refresh: true,
pageSizes: true,
buttonCount: 5
},
filterable: true,
serverPaging: true,
columns: columns,
});
var grid = $("#grid").data("kendoGrid");
grid.table.on("click", ".checkbox", Grid_Click);
wnd.content($("#detail_items").html());
}
|
Controller
public ActionResult
listAllCustomers(DataSourceRequest request)
{
try
{
//與資料庫有緊密關係的Function
, 作者都集中在MODEL 層…方更後續彈性切換
IQueryable<dynamic> data = entityMessageModel.listAllCustomerFromTCS(request.Page);
var result = new DataSourceResult()
{
//取回JSON格式 Data: [{},{},{}], 取回JSON的關健字為Data
Data = data,
Total =
entityMessageModel.totalCustomersCount()
};
var json = JsonConvert.SerializeObject(result);
return new MyJsonResult(json);
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
|
五、成果展示
彈出Ifram視窗, 並透過Kendo UI 讀取JSON
沒有留言:
張貼留言