2011-11-10 22 views
3

私はdojoフレームワークに基づいてWebアプリケーションを開発しています。jsonRest dojoの複雑な構造

dojox.data.JsonRestStoreをサーバーとの通信に使用することにしました。

例えば、私は、JSONでのご注文(eコマース)のこの表現を持っている:

{ 
id: int, 
name: str, 
date: str, 
items: [ 
    { 
     id: int, 
     name: str, 
     pcs: int, 
     price: int, 
     total: int 

    }, ... 
] 
} 

注文は、いくつかの基本的な属性(ID、名前、日付)を有し、それはまた、注文した商品の配列が含まれています。

これは良い(REST)デザインであるかわかりませんが、注文したアイテムが別のリソース(別のjsonRestStoreなど)にあるかどうかは疑問です。

Dojoフォームの注文の基本属性とdojo Datagridの注文アイテムを表示する際に、現在のオブジェクトモデルに問題があると思います。

私の質問は、私の現在のアプローチはOKです - RESTクライアントアプリケーションを作成する方法ですか?また、dojoのDataGridでサンプルフォームを実装する正しい方法は何ですか?

答えて

3

あなたのデザインはRESTfulですが、それを必要とするRESTアーキテクチャには何もありませんが、ほとんどの人はあなたのリソースを分けておくことが最善の方法だと思います。 Restful Web Servicesをチェックアウトすると、これはリソース指向アーキテクチャーとして記述されます。

注文とアイテムを別々のJsonRestStoresに保管し、Dojoフォームを使用してOrderオブジェクトを表示し、Dojo DataGridを使用して注文のアイテムを表示する例を試しました。私はコードが簡単だと思うし、コードにいくつかのコメントを追加して試してみてください。

例のためのダミーデータを提供するために、単純なASP.NET MVC 3バックエンドを作成しました。私はあなたのコードの「表示」の部分で、実際にのみ関心があるものの、バックエンドのコードはまた、あなたが持っているバックエンドのコードのいずれかを把握したり変更を助けることが、同様にそのコードを掲載している

ビュー:

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %> 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 

<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
    <title>JsonRestStore Datagrid Example</title> 

<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/dojo/1.6.1/dojo/resources/dojo.css"/> 
<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/dojo/1.6.1/dijit/themes/tundra/tundra.css"/> 
<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/dojo/1.6.1/dojox/grid/resources/Grid.css"/> 
<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/dojo/1.6.1/dojox/grid/resources/tundraGrid.css"/> 

<script type='text/javascript' src='https://ajax.googleapis.com/ajax/libs/dojo/1.6.1/dojo/dojo.xd.js' djConfig="parseOnLoad:true"></script> 

<script type="text/javascript"> 

    dojo.require("dojox.data.JsonRestStore"); 
    dojo.require("dojox.grid.DataGrid"); 
    dojo.require("dijit.form.DateTextBox"); 
    dojo.require("dojox.grid.cells.dijit"); 
    dojo.require("dojo.date.locale"); 
    var item_structure = null; 

    dojo.ready(function() { 
     setItemTableStructure(); 
     //retrieve a single order 
     //expects json to look like 
     // {"Id":2,"Name":"Order Name 2","Date":"\/Date(1321135185260)\/","Items":{"Ref":"/Order/2/Items"}} 
     order_store = new dojox.data.JsonRestStore({ target: "/Order/2", idAttribute: "Id" }); 

     order_store.fetch({ 
      onComplete: function (item) { 
       //this method is called after an item is fetched into the store 
       //item here is the order json object 
       var orderId = new dijit.form.TextBox({ value: order_store.getValue(item, 'Id') }, 'orderId'); 
       var orderName = new dijit.form.TextBox({ value: order_store.getValue(item, 'Name') }, 'orderName'); 
       var orderDate = new dijit.form.DateTextBox({ value: parseJsonDate(order_store.getValue(item, 'Date')) }, 'orderDate'); 
       var items = order_store.getValue(item, 'Items').Ref; 

       //make a call to retrieve the items that are contained within a particular order 
       //expects a json object that looks like 
       //[{"Ref":"/Item/1"},{"Ref":"/Item/2"},{"Ref":"/Item/3"},{"Ref":"/Item/4"},{"Ref":"/Item/5"}] 
       var xhrArgs = { 
        url: items, 
        handleAs: "json", 
        load: loadOrder, //main method 
        error: function (error) { 
         console.log(error); 
        } 
       } 
       var deferred = dojo.xhrGet(xhrArgs); 
      } 
     }); 
    }); 

    //This is the main method 
    function loadOrder(data) { 
     var itemIds = ""; 
     dojo.forEach(data, function(item, i){ 
      itemIds += item.Ref.charAt(item.Ref.length-1); 
      itemIds += ","; 
     }); 
     itemIds = itemIds.substring(0, itemIds.length-1); 

     //build the backend to accept a comma seperated list of item ids 
     //like /Item/1,2,3 
     item_store = new dojox.data.JsonRestStore({target:"/Item/" + itemIds, idAttribute:"Id"}); 
     items = new dojox.grid.DataGrid({ 
      name: "items", 
      formatter: function(date) { 
         if (date) return dojo.date.locale.format(parseJsonDate(date), { 
          selector: "Date" 
         }) 
        }, 
      structure: item_structure, 
      store: item_store 
     }, dojo.byId('orderItems')); 

     items.startup(); 
    } 

    function setItemTableStructure() { 
     item_structure = [ 
     { 
      field: 'Id' 
     }, 
     { 
      field: 'Name' 
     }, 
     { 
      field: 'Price' 
     }, 
     { 
      field: 'Date', 
      type: dojox.grid.cells.DateTextBox, 
      widgetProps: { 
       selector: "Date" 
      }, 
      formatter: function(v) { 
       if (v) return dojo.date.locale.format(parseJsonDate(v), { 
        selector: 'Date' 
       }) 
      } 
     }]; 
    } 

    function parseJsonDate(jsonDate) { 
     var offset = new Date().getTimezoneOffset() * 60000; 
     var parts = /\/Date\((-?\d+)([+-]\d{2})?(\d{2})?.*/.exec(jsonDate); 

     if (parts[2] == undefined) 
      parts[2] = 0; 

     if (parts[3] == undefined) 
      parts[3] = 0; 

     return new Date(+parts[1] + offset + parts[2]*3600000 + parts[3]*60000); 
    } 
    </script> 
    </head> 
    <body> 
    <h1>Json Rest Store with DataGrid Example</h1><br /> 

    <form style='margin: 10px' action='post'> 
    <h2>Order</h2> 
    <input id='orderId' /> 
    <input id='orderName' /> 
    <input id='orderDate' /> 
    </form> 
    <h2>Items</h2> 
    <div id='orderItems'></div> 
    </body> 
</html> 

モデル:

using System; 

namespace OrdersRestService.Models 
{ 
    public class Item 
    { 
     public int Id { get; set; } 
     public string Name { get; set; } 
     public double Price { get; set; } 
     public DateTime Date { get; set; } 
    } 
} 

public class Order 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public DateTime Date { get; set; } 
    public Reference Items { get; set; } 
} 

public class Reference 
{ 
    public string Ref { get; set; } 
} 

コントローラ:

namespace OrdersRestService.Controllers 
{ 
    public class OrderController : Controller 
    { 
     public ActionResult Index(string id) 
     { 
      Order order = new Order 
           { 
            Id = Convert.ToInt32(id), 
            Name = "Order Name " + id, 
            Date = DateTime.Now, 
            Items = new Reference 
               { 
                Ref = "/Order/" + id + "/Items" 
               } 
           }; 

      return Json(order, JsonRequestBehavior.AllowGet); 
     } 

     public ActionResult Items() 
     { 
      List<Reference> items = new List<Reference>(); 

      for (int i = 1; i <= 5; i++) 
      { 
       Reference r = new Reference(); 
       r.Ref = "/Item/" + i; 
       items.Add(r); 
      } 

      return Json(items, JsonRequestBehavior.AllowGet); 
     } 
    } 

    public class ItemController : Controller 
    { 
     public ActionResult Index(string id) 
     { 
      List<Item> items = new List<Item>(); 
      foreach (string itemid in id.Split(',')) 
      { 
       Item item = new Item 
            { 
             Id = Convert.ToInt32(itemid), 
             Name = "Item Name " + itemid, 
             Date = DateTime.Now, 
            }; 
       items.Add(item); 
      } 

      return Json(items, JsonRequestBehavior.AllowGet); 
     } 
    } 

    public class HomeController : Controller 
    { 
     public ActionResult Index() 
     { 
      return View(); 
     } 
    } 
} 

グローバル.aspx.cs

public class MvcApplication : System.Web.HttpApplication 
{ 
    public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
    { 
     filters.Add(new HandleErrorAttribute()); 
    } 

    public static void RegisterRoutes(RouteCollection routes) 
    { 
     routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 

     routes.MapRoute(
      "DefaultWithAction", // Route name 
      "{controller}/{id}/{action}", // URL with parameters 
      new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults 
     ); 
    } 

    protected void Application_Start() 
    { 
     AreaRegistration.RegisterAllAreas(); 

     RegisterGlobalFilters(GlobalFilters.Filters); 
     RegisterRoutes(RouteTable.Routes); 
    } 
} 
+0

複雑な例をありがとう! – JoshuaBoshi

1

あなたのアプローチは問題ありません。 RESTクライアントは、データがリレーショナルデータベースであるかフラットテキストファイルであるかにかかわらず、データの格納方法を知る必要はありません。注文エンドポイントに転記するときは、必ずオーダーアイテムを含めることができます。この設計はより高速で、サーバー要求も少なくて済みます。注文を作成するために一度投稿するのではなく、注文IDを待ってからすべてのアイテムを投稿した後、すべてを一度投稿します。

RESTは、POST、DELETE、GET、PUTなどの既存のHTTP動詞を使用して、エンドポイントを簡略化します。アイデアは、アプリケーションインターフェイスの一部としてHTTPプロトコルを使用することです。あなたのモデルをどのように設計するかは決まっていません。

+0

ありがとうございました。それは私をたくさん助けました。 – JoshuaBoshi

関連する問題