Starcounter
HomeDownloadDocsCommunity
2.3.1
2.3.1
  • Starcounter Documentation
  • Getting Started
  • Starcounter
    • Collapsing the Stack
      • Complexity and Scalability Tradeoff
      • The Future of Micro-Services
      • 10 Benefits of Collapsing the Stack
    • Integrated Database and Web Server
  • Hello World - Tutorial
    • Create a Database Class
    • Create a Real Time UI
    • First Interactive UI
    • Computed Properties
    • Expense Tracker
    • Cancel and Delete
    • The Next Step
  • Guides
    • Database
      • Database Classes
      • Data manipulation
      • Object Identity and Object References
      • Querying with SQL
      • Data Types
      • Relations
      • Inheritance
      • Sharing data
      • Database Configuration
      • Comparing Database Objects
      • Referential Integrity and Constraints
    • SQL
      • Identifiers
      • Path Expressions
      • Data operators
      • Joins
      • Aggregates
      • Comparisons and Logical Operators
      • Sorting
      • Fetch
      • Offset Key
      • Indexes
      • Literals
      • Query Plan Hints
      • Reserved words
      • Query for Database Classes
      • SQL Isolation Between Applications
    • Transactions
      • Short-Running Transactions
      • Long running transactions
      • Using Transactions
      • Running Background Jobs
      • Commit Hooks
    • Typed JSON
      • JSON-by-example
      • Code-Behind
      • Data Bindings
      • Callback Methods
      • Responding with JSON
      • Accepting JSON in Requests
      • Primitive Arrays and Single Value Types
      • Typed JSON Internals
    • Blendable Web Apps
      • Starcounter MVVM
      • Palindrom
      • Client-Side Stack
      • Sessions
      • HTML Views
      • App Shell
      • Web Components
      • View Attaching
      • View Composing
      • HTML Compositions
      • HTML Views Blending Guidelines
      • Avoiding CSS conflicts
      • Debugging
    • Network
      • HTTP
      • Internal Self Calls
      • Middleware
      • Anonymous or Substitute Handlers
      • URL Aliases and Redirects
      • Network Gateway
      • Static File Server
      • External HTTP Calls
      • WebSocket
      • Avoiding URI conflicts
      • TCP Sockets
      • UDP Sockets
    • Publishing Apps
    • Working with Starcounter
      • Release Channels
      • Starting and Stopping Apps
      • Administrator Web UI
      • Star CLI
      • StarAdmin CLI
      • StarDump CLI
      • Working in Visual Studio
      • Error Log
      • Using HTTPS on NGINX
      • Using HTTPS on IIS
      • Run Starcounter in Production
      • Weaver
      • Investigating App Crashes
      • Configuration Structure
      • Database Refactoring
      • Using Unload/Reload to Modify Database Schema
      • Kernel Questions and Answers
      • Log Files
  • Cookbook
    • Attach an HTTP Request to an Existing Long-Running Transaction
    • Cookie-Based Authentication
    • Timestamp on Object Creation
    • Creating Strongly Typed JSON Collections
    • Migrating From 2.2 to 2.3+
    • Multiple Pages
    • Icons
    • Proposed Project Structure
    • Acceptance Testing with Selenium
    • Requesting a User to Authenticate
    • How to delete unused tables and columns
Powered by GitBook
On this page
  • Introduction
  • Default Bindings
  • Binding to Database Objects
  • Binding to Code-Behind Properties
  • Mixing Database and Code-Behind Bindings
  • Different Types of Bindings
  • Auto
  • Bound
  • Unbound
  • Parent
  • Rules When Bindings are Created
  • Modify Bindings
  • Opting Out of Bindings
  • Binding to Properties With Different Names
  • Binding to Custom Properties in Code-Behind
  • Binding to a Deep Property
  • Setting Type of Binding for Children
  • Specify Data Type
  • IBound
  • IExplicitBound
  1. Guides
  2. Typed JSON

Data Bindings

Introduction

Properties declared in Typed JSON can be bound to either a property in the code-behind file or a CLR object that exposes one or more public properties. Properties that are bound will read and write the values directly to the underlying object with no need to manually transfer the values to the view-model.

Default Bindings

Binding to Database Objects

To bind a Typed JSON object to a database object, the Data property is used.

Consider the following JSON file:

PersonPage.json
{
   "FirstName": "",
   "LastName": "",
}

To bind the Typed JSON object PersonPage defined above to a database class Person, the following code can be used:

Program.cs
using Starcounter;

namespace MyApp
{
    [Database]
    public class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string FullName => FirstName + " " + LastName;
    }

    class Program
    {
        static void Main()
        {
            Db.Transact(() => // Add a new Person instance to the database
            {
                new Person()
                {
                    FirstName = "Steve",
                    LastName = "Smith"
                };
            });

            Handle.GET("/GetPerson", () =>
            {
                var person = Db.SQL<Person>("SELECT P FROM Person P").First; // Retrieve a database object from the database

                var json = new PersonPage() 
                {
                    Data = person // Bind the database object to the Typed JSON object
                };

                return json;
            });
        }
    }
}

The PersonPage object will now look like this: {"FirstName":"Steve","LastName":"Smith","FullName":"Steve Smith"}.

Starcounter recognizes that the properties in PersonPage and Person object have the same name and populates the values in the Typed JSON accordingly. This is the default way that bindings are created.

Binding to Code-Behind Properties

In addition to binding to database objects, Typed JSON properties can also be bound to code-behind properties.

PersonPage.json
{
   "FirstName": "Steven",
   "LastName": "Smith",
   "FullName": ""
}
PersonPage.json.cs
using Starcounter;

namespace MyApp
{
    partial class PersonPage : Json
    {
        public string FullName => FirstName + " " + LastName;
    }
}
Program.cs
using Starcounter;

namespace MyApp
{
    class Program
    {
        static void Main()
        {
            Handle.GET("/GetPerson", () =>
            {
                return new PersonPage(); // {"FirstName":"Steven","LastName":"Smith","FullName":"Steven Smith"}
            });
        }
    }
}

Mixing Database and Code-Behind Bindings

When mixing database and code-behind bindings, the code-behind bindings take presidence. This means that if there is a database property and code-behind property with the same name, the code-behind property will be the one that's used.

Different Types of Bindings

There are different settings that can be specified on each property or JSON object. Auto, Bound, Unbound or Parent.

Auto

When the binding is specified as auto (which is the default setting) each property is matched against the code-behind and the data object (if any). If a code-property with the same name or with a name specified as binding is found the JSON property is treated as bound and getting and setting values to it will get and set the value on the underlying property.

If no matching property is found, the JSON property is treated as unbound and values will be stored in the JSON.

Bound

When a JSON property is specified as bound a compiler error or runtime error, depending on if the type to bind to is specified, is thrown. A JSON property declared as Bound must match a property in the code-behind or data object.

Unbound

An unbound JSON property will store the value in the JSON.

Parent

The same setting as specified on a parent is used, which will be one of the above (auto, bound, unbound).

Rules When Bindings are Created

  1. If a code-behind file exists, a property is searched for there.

  2. If a property was not found in the code-behind or no code-behind exists, a property in the data object is searched for.

  3. If no property was found in steps 1 and 2 and the binding is set to Auto, the property will be unbound. If binding was set to Bound an exception will be raised.

Modify Bindings

There are different ways to modify bindings so that they do not bind the default way.

All binding modifications are done in a static constructor in the code-behind file. Like so:

PersonPage.json.cs
using Starcounter;

namespace MyApp
{
    partial class PersonPage : Json
    {
        static PersonPage()
        {
            // Modifications go here
        }
    }
}

Opting Out of Bindings

In some cases we want to make sure that a specific property is not bound. This can be achieved by setting the value of Bind to null;

For example:

PersonPage.json.cs
partial class PersonPage : Json
{
    static PersonPage()
    {
        DefaultTemplate.FullName.Bind = null;
    }
}

Setting the Bind property to null in this case ensures that the Typed JSON property FullName is not bound to any database, or code-behind, property.

Binding to Properties With Different Names

If a property should be bound to a property that has a different name than the property in the JSON, a binding value can be set.

PersonPage.json.cs
public class PersonPage : Json
{
    static PersonPage()
    {
        DefaultTemplate.FirstName.Bind = "LastName";
        DefaultTemplate.LastName.Bind = "FirstName";
    }
}

The resulting JSON looks like this: {"FirstName":"Smith","LastName":"Steve","FullName":"Steve Smith"}.

Binding to Custom Properties in Code-Behind

PersonPage.json.cs
public class PersonPage : Json
{
    static PersonPage()
    {
        DefaultTemplate.FullName.Bind = "CustomFullName";
    }

    public string CustomFullName => FirstName + FirstName + " " + LastName; 
}

Binding to a Deep Property

It is also possible to bind to deep properties by providing full path to the property. Here, the property FriendName is bound to the deep property Friend.FirstName.

PersonPage.json
{
  "FirstName": "",
  "FriendName": ""
}
PersonPage.json.cs
using Starcounter;

namespace MyApp
{
    partial class PersonPage : Json
    {
        static PersonPage()
        {
            DefaultTemplate.FriendName.Bind = "Friend.FirstName";
        }
    }
}
Program.cs
using Starcounter;

namespace MyApp
{
    [Database]
    public class Person
    {
        public string FirstName { get; set; }
        public Person Friend { get; set; }
    }

    class Program
    {
        static void Main()
        {
            Db.Transact(() =>
            {
                var friend = new Person() { FirstName = "Bilbo" };

                new Person()
                {
                    FirstName = "Steve",
                    Friend = friend
                };
            });

            Handle.GET("/GetPerson", () =>
            {
                Person person = Db.SQL<Person>("SELECT P FROM Person P WHERE P.FirstName = ?", "Steve").First;
                var json = new PersonPage();
                json.Data = person;
                return json;
            });
        }
    }
}

The resulting JSON from this example looks like this: {"FirstName":"Steve","FriendName":"Bilbo"}.

Setting Type of Binding for Children

Typed JSON objects that contain children can specify how the type of bindings on its children.

By setting the property BindChildren, each child that don't specify it's own binding, i.e. use the Parent option will have the binding decided by the parent.

Setting the value in the code-behind from the BindingStrategy enum:

PersonPage.json.cs
partial class PersonPage : Json
{
    static PersonPage()
    {
        DefaultTemplate.BindChildren = BindingStrategy.Bound;
    }
}

The enum has the following values: "Auto", "Bound", and "Unbound".

It is not allowed to set the value for this property to BindingStrategy.UseParent. An exception will be raised in this case.

Specify Data Type

Denoting a specific type that is used as data-object is optional but comes with some benefits.

If the JSON object is static, that is all properties are known compile-time, you will get an error during compilation if bound properties are invalid, instead of getting a runtime error on first use. The Data property itself will also be typed to the correct type which means that you don't need to cast the data-object when using it.

IBound

The JSON code-behind class has to implement IBound<T> to set custom data type.

PersonPage.json.cs
[PersonJson_json]
public partial class PersonJson : Json, IBound<MyNamespace.Person>

Note: empty JSON objects do not have code-behind classes so it is not possible to declare a custom data type for them.

IExplicitBound

IExplicitBound is an improved implementation of IBound. They are used the exact same way, though IExplicitBound allows more control over the bindings.

When using IExplicitBound, properties in JSON-by-example are expected to be bound. This allows the pinpointing of failed bindings which otherwise could go unnoticed. If the JSON-by-example looks like this:

PersonPage.json
{
  "Name": "",
  "Age": 0,
  "Address": ""
}

And the database class looks like this:

Person.cs
public class Person
{
  public string Name { get; set; }
  public long Age { get; set; }
  public string Address { get; set; }
}

If the code-behind includes IExplicitBound like this:

PersonPage.json.cs
public class PersonPage : Json, IExplicitBound<Person>

Then it will compile successfully. If public long Age was removed, then the following error would be displayed: 'Person' does not contain a definition for 'Age'. The reason for this is that IExplicitBound would look for a database property corresponding to Age and fail.

Since IExplicitBound expects all values to be bound to something, properties that are not intended to be bound have to be explicitly unbound. As noted above, it will not compile without this. A static constructor can be used in order to explicitly unbind these properties. This is how it would look:

PersonPage.json.cs
static PersonPage()
{
    DefaultTemplate.Age.Bind = null;
}

Now, the code will compile successfully because it is explicitly described that the Age property will not be bound. This is further described in the section "Opt-out of Bindings".

PreviousCode-BehindNextCallback Methods

Last updated 7 years ago

To accomplish what was demonstrated in the by using code-behind properties instead of database properties, the following code can be used:

By applying this to the example in the , the resulting JSON would be {"FirstName":"Steve","LastName":"Smith","FullName":""}. Since the FullName property is not bound, it will not contain any value.

For example, to bind the Typed JSON property FirstName to the database property LastName in the example in the and vice versa to essentially switch the names around, the following code can be used:

Since it is possible to , it is also possible to bind to custom properties in the code-behind. For example:

The resulting JSON looks like this with the example in the : {"FirstName":"Steve","LastName":"Smith","FullName":"SteveSteve Smith"}.

previous example
bindings to database objects section
bindings to database objects section
bind to properties with different names
bindings to database objects section