顯示具有 Entity Framework 標籤的文章。 顯示所有文章
顯示具有 Entity Framework 標籤的文章。 顯示所有文章

2014年10月4日 星期六

[鐵人30天]當ASP.NET MVC 遇見 Angular.js MVC 客戶管理系統(7) - 取得WebAPI資料(Angular.js)

* 本篇目標

利用Angular.js像WebAPI取得資料

* 前言

以往開發前端多半倚賴jQuery,今年接觸到了Google所推出的JavaScript libery , 他是一個前端MVC的Freamwork,Study過後,認為將前端改寫成NG,程式會比較有彈性,故開始投入學習。個人認為學習曲線NG比學習jQuery還要高,本系列文章並不是針對NG做一個詳細介紹,故會採用"做中學"的方式,來實作ASP.NET MVC如何搭配Angular.js做開發。

* Visual Studio 安裝

我們一樣在Web專案使用Nuget安裝

4ae8c68e39ce4cca9b2fe982736d2a4f

會看到Scripts資料夾裡有非常的多的Angular套件,這是因為Angular.js模組化做得非常好,故如果沒有要用到的功能,就不用載入進來,而相關的模組有什麼功能可以用,其實可以google ng加檔名,就可以查到官方文件或文章,如 “ng-resource”。

e7f4127b09af48a0bdd1a59b23ba2450

接著我們打開MVC的 View,Shared資料夾_Layout.cshtml檔案,載入angular.min.js。

_Layout有點像是ASP.NET WebForm的Master Page,可以把一些共用的html,js,css放在這,頁面各自的View就不用存在於重複的程式碼 e.g 選單列。

4280682be0ba4eee9669dd2e0d31bb20

* 修改CustomerController

上一篇我們取得WebAPI資料的方式,是採取C# WebClinet的方式,在Contoller轉成ViewModel在給View,採用Angular.js將會做一些小修改。首先我們將程式碼註解起來。

219dc17ca88d4f54a3c278980a068d79

接著我們改寫View使用Angular.js的語法,會發現Visual Studio 2013 已經很貼心的將NG的語法變為紫色了,這讓開發更加的清楚,以下依步驟做介紹

ng-app : 可以說是Angular.js的起始點,子元素才會看得懂Angular.js的語法

ng-controller : 因為是MVC架構,故我們會在Scripts新增一個Controller的function,並指定這個Div使用CustCtrl

$scope : 可以想成是"前端"的ViewModel,又有點像是C#的Class,可以將變數定義在此,以此例,我們將後端取回的Customer JSON資料,丟給$scope裡的Customer。

$http : 在與後端資料溝通,我們可以使用$http來對Server API進行,POST . GET . PUT .DELETE,以此例我們向我們WebAPI取得資料,丟給$scope裡的Customer;失敗的話則給$scope一個變數error,並秀在Div裡。

$ng-repeat : 此語法可以讓我們很輕鬆的寫出迴圈功能,如Customer裡面的資料,我們將資料一筆一筆讀出來,並變成html table裡的tr列。

8c326a0bc5104c188986a7d4ab413b1e

結果畫面

07a6757c363749109aabd426f4892e7a

* 雙向繫結

在Angular.js的MVC架構,都有Data Binding的特性,也就是今天在Model改變了一些值,或在View改變了一些值,是兩方都會產生變化的。

image

用講的不太清楚,故我們來玩個小範例:

http://jsfiddle.net/kyleshen/5un6argf/

TestCtrl裡面Model有 Day . Name兩個變數,及一個事件 Add,將Day加1

ng-model : 可以指定這個input標籤 對應到Model的名稱

ng-click : 點選Click的時候去執行哪個事件

08cc1b432f954b36b1e13e27d00ef5fb

* 後記

此篇介紹了一些Angular.js的一些基本用法,下一篇預計來換個輕鬆主題,來介紹如何利用一些工具來快速美化我們的網站。

Angular.js逐步學習文章推薦:

男丁格爾Angular.js教學 http://abgne.tw/category/angularjs

黑暗執行緒Angular.js系列 http://blog.darkthread.net/blogs/darkthreadtw/archive/tags/AngularJS/default.aspx

 

 

本系列程式原始碼請至我的Github下載  https://github.com/kyleap

** 如內容有誤請告知,將進行修改,謝謝 **

2014年10月3日 星期五

[鐵人30天]當ASP.NET MVC 遇見 Angular.js MVC 客戶管理系統(6) - 取得WebAPI資料

* 本篇目標

建置一個RESTful風格的Web服務

* Web API 2.2

現在開發通常會考慮到多平台,如手機平板等等,但關於資料來源不可能針對每個平台都去寫一樣的Code,早期.NET解決方案有Web Service、WCF Service的應用,.NET Freamwork 4.5後推出了更輕量化的Web API服務,搭配MVC架構開發上變得非常的輕鬆,本系列文章使用Web API 2.2。

延伸閱讀  [Web API] 初探 Web API 筆記

* 建置Web API

我們再UI層新增Web專案時,其實就已經勾選安裝Web API了,如果忘記選擇了,可以透過Nuget安裝。

a8dcf173f2614837b442e02a913799a9

WebAPI開發習慣,我通常會再專案底下建一個API資料夾,接著點選右鍵,加入Web API控制器

f247eb1d2af848babad98b146db3126a

建立以後,她預設會幫我們建立CRUD function,我們就針對每個function去改寫,注意Web API也是MVC架構,命名也是為Controller結尾,但不同的是Web API是繼承ApiController。

9c6601b5d9a54583bdc1d37aab8aae37

接下來我們將Get稍作修改,向BLL層要客戶資料,HttpReponseMessage可以很方便的讓前端知道是否有發生錯誤,並回傳自己定義的Object。

7b24c666c2444fae98ab71461d75553d

接著在瀏覽器執行,輸入 host/api/Customer即可取得我們的資料

a109f7e377e44ef48a866cb63d5a45ad

* 於MVC的Controller及View列出資料

接著我們再專案裡Contoller,新增一個CustomerController

e7bede476978464188a15b911f382cc7

在Controller使用WebClinet像Web API要資料

3dded709ab774d879f9ecd1cf1d1df83

在新增一個View,套入原本樣板的主體Layout

b47227cee9764b49a4fcc1a2ebd5c62b

使用ViewModel,並用好用的Razor語法印出資料

39321e5640db412282e6ee4a0567e661

結果畫面

8dc19f6dfc0745b28cd4d067c85db1f5

* 後記

我認為Web API是個趨勢,未來我也一定會採用這種架構,一方面MVC的Contoller不會有太多跟BLL Service溝通的code,且對於多專案平台,都可向WebAPI取得資料。但實務上我並不會將跟Web API的Code寫在Controller裡,而會是在前端的View,也就是Angular.js登場的時候了!

延伸閱讀ASP.NET MVC - 第一個Web API,Hello Web API

ASP.NET WEB API 心得筆記 (4) WEB API ROUTING

MSDN – MVC Razor語法

 

本系列程式原始碼請至我的Github下載  https://github.com/kyleap

** 如內容有誤請告知,將進行修改,謝謝 **

2013年12月27日 星期五

KendoUI & ASP.NET MVC系列文章 - 處理CRUD-繼續完成新增、修改、刪除

前言

前一篇我們已經完成利用Ajax來讀取後端資料顯示於Grid,而此篇就會將新增、修改、刪除功能接續完成

CRUD的 Create - 新增

Controller

利用原本樣板產生的程式做一些修改,原本程式如下

image

將上面程式修改為以下,透過MVC的Model Bindder可以接收前端傳來的Customers物件,並依情況回傳是否新增成功

image

View

將dataSrc新增一個Create function,指向後端的CreateCustomer,並在完成後alert處理結果

 image

Schema部分新增model定義,讓KendoUI知道你的模組結構,並且可設定一些欄位驗證

image

接著在屬性部分新增toolbar及editable,editable模式可分為inline(直接在Gird新增一個)或者是popup(彈跳視窗)方式,此例我們希望新增時是跳出一個燈箱視窗

image

結果圖

這樣就完成,在以往我們可能自己要實做View的頁面,現在KendoUI都幫你做好好的,且表單也排得很整理 lol

image


CRUD的Update-編輯

Controller

基本上跟新增大同小異,我們在Controller新增EditCustomer的JsonResult

image 

View

新增一個Update function

image

在columns多一個command成員,並設定edit按鈕(這邊也可以自訂義Button標籤)

image

這樣就完成編輯燈箱視窗了!!

image

CRUD的Delete-刪除

Contoller (這邊就不解釋了)

image

View

image

image

後記

以上是一種實做CRUD的方式,但其實做法有很多種,譬如你也可自訂新增、編輯的View去實做,或者你也可以自訂一些查詢欄位POST到後端去,關於版面,如果要修改中文的顯示其實也可以做到,之後也會分享一些實做心得PO上來。而下一篇,預計完將後端改成用WebAPI + OData的方式實做 =V=

完成程式碼

Contoller

public class GridAjaxController : Controller
{
private NorthwindEntities db = new NorthwindEntities();

// GET: /GridAjax/
public ActionResult Index()
{
return View();
}

public JsonResult GetCustomer(KendoGridRequest request)
{
try
{
var result = db.Customers.ToList();
return Json(new KendoGrid<Customers>(request, result), JsonRequestBehavior.AllowGet);
}
catch (Exception)
{
Dictionary<string, object> error = new Dictionary<string, object>();
error.Add("ErrorCode", -1);
error.Add("ErrorMessage", "讀取資料失敗!");
return Json(error);
}
}

// GET: /GridAjax/Details/5
public ActionResult Details(string id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Customers customers = db.Customers.Find(id);
if (customers == null)
{
return HttpNotFound();
}
return View(customers);
}

// GET: /GridAjax/Create
public ActionResult Create()
{
return View();
}

[AcceptVerbs(HttpVerbs.Post)]
public JsonResult CreateCustomer(Customers customers)
{
if (ModelState.IsValid)
{
if (TryUpdateModel(customers))
{
db.Customers.Add(customers);
db.SaveChanges();
return Json("新增成功!!");
}
}
return Json("新增失敗!!");
}

public JsonResult EditCustomer(Customers customers)
{
if (ModelState.IsValid)
{
db.Entry(customers).State = EntityState.Modified;
if (TryUpdateModel(customers))
{
db.SaveChanges();
return Json("更新成功!!");
}
}
return Json("更新失敗!!");
}

[AcceptVerbs(HttpVerbs.Post)]
public JsonResult DeleteCustomer(string CustomerID)
{
Customers customers = db.Customers.Find(CustomerID);
db.Customers.Remove(customers);
if (TryUpdateModel(customers))
{
db.SaveChanges();
return Json("刪除成功!!");
}
return Json("刪除失敗!!");
}

protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}

View

@model IEnumerable<KendoUI.Model.Customers>

@{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/BaseLayoutPage.cshtml";
}

@section scripts
{
<script type="text/javascript">
$(function () {

//資料來源物件改用Ajax
var dataSrc = new kendo.data.DataSource({
transport: {
read: {
type: "POST",
url: "/GridAjax/GetCustomer",
dataType: "json",
complete: function (response, status) {
if (response.responseJSON.ErrorCode == -1) {
alert(response.responseJSON.ErrorMessage);
}
}

},
update: {
url: "/GridAjax/EditCustomer",
dataType: "json",
type: "POST",
complete: function (response, status) {
alert(response.responseJSON);
}
},
create: {
url: "/GridAjax/CreateCustomer",
dataType: "json",
type: "POST",
complete: function (response, status) {
alert(response.responseJSON);
}
},
destroy: {
url: "/GridAjax/DeleteCustomer",
dataType: "json",
type: "POST",
complete: function (response, status) {
alert(response.responseJSON);
}
},
},
schema: {
data: function (d) {
return d.data;
},
total: function (d) { return d.total; },
model: {
id: "CustomerID",
fields: {
product: { editable: false, nullable: false },
CompanyName: { validation: { required: true } },
ContactName: { validation: { required: true } },
City: { validation: { required: true } }
}
}
},
pageSize: 5,
serverPaging: true,
serverSorting: true
});

$("#gridData").kendoGrid({
dataSource: dataSrc,
columns: [
{ field: "CustomerID", title: "CustomerID" },
{ field: "CompanyName", title: "CompanyName" },
{ field: "ContactName", title: "ContactName" },
{ field: "City", title: "City" },
{ command: ["edit","destroy"], title: "&nbsp;", width: "160px" }
], //columns的field對應到customer資料表的欄位
sortable: true,
pageable: true,
filterable: true,
width: 800,
toolbar: ["create"],
editable: {
mode: "popup", //使用Popup的模式編輯資料
update: true, // 若設定為True,當按下Update才server資料
}
});
});
</script>
}
<div id="gridData"></div>


延伸閱讀




2013年12月4日 星期三

[EF]找出EntityValidationErrors的明細錯誤訊息

在開發MVC使用EntityValidationErrors時,如果遇到如下圖錯誤:

QQ截圖20131204154904

利用瀏覽器的開發者工具也無法找到錯誤 e.g Chome F12 -> Network :

image

只看到Model驗證失敗,卻找不到很明確的錯誤訊息。

這時我們就可以用EntityValidationErrors來catch錯誤訊息:

try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException e)
{
string ErrorMsg = e.Message;
}
catch(Exception e)
{

}


可以發現是某個欄位為空值,導致新增失敗


image