Code Monkey home page Code Monkey logo

resgateclientnet's Introduction

ResGateClientNet

Implementation of ResGate Client in .NET

Very liberal license, MIT

No credit (in binary form) is required

Basics

Subscriber model is based on idea of tokens. You will get IDisposable token each time you subscribe to any resource. As long as this token is not disposed you will get updates to that resource.

Implementation support reconnecting on failure, and server polling (for example if you have more then one end-point). Registered resources survives reconnection (they will be resubscribed)

Requires Newtonsoft.JSON and WebSocket.Client

Requires ResGate version at least 1.2.0

Examples

EXAMPLE 1. Run this server app - Book Collection

EXAMPLE 2. Run this server app - Password Authentication

Roadmap

Last updated: May, 24th, 2020

ToDo

  • Support for reconnection on failure
  • Get methods
  • Subscribe and unsubscribe methods
  • Call methods
  • Auth methods
  • Error handling
  • Re-auth on reconnect (or anything else, actually)
  • First release on nugets

API

// Important: all callbacks are fired from secondary thread.
// Locking and syncing is up to you!

// The action can be used to supply different Uris on each attempt.
// The reconnection is automatic
var settings = new Resgate.Settings(() => new Uri("ws://localhost:8080"));

// Failed means something terrible has happen, and no reconnection can fix that.
// Currently supported are:
//  - UnsupportedVersion and VersionNegotiationFailed
//      They means the server is up, accessible, but has invalid version.

settings.Failed += (o, ev) =>
{
    Console.WriteLine("Failed to connect due to " + ev.Reason.ToString());
}

// If there is a problem with subscribe request, it will be reported here
// (as subscription must be re-applied every new reconnection after
// connection has been lost)
settings.Error += (obj, evnt) =>
{
    Console.WriteLine("Failed to subscribe " + evnt.Rid + " because of " +
                      evnt.Error.Message);
}

// Define class that will hold our data. You can have subobjects, and they will
// be populated via indirect resource IDs (RIDs). Oh, and cyclic references
// are supported too!
class Book
{
    public string title;
    public string author;
}

// Create actual client
using (var client = new Resgate.Client(settings))
{
    // Get some basic data (non-subscribed version)
    // Important: this will block waiting for reconnection if currently disconnected
    List<Book> data = await client.GetCollection<Book>("library.books");
    Book book = await client.GetModel<Book>("library.book.1");
    
    
    // Now for the wunderwaffe - collection (or model) that will automatically update
    // if server updates the resources. Definition for Initial, Addded, Changed, Removed below
    TokenCollection token1 = await client.SubscribeCollection<Book>
                           ("library.books", Initial, Added, Changed, Removed)
    
    // as long as token remains alive, the four methods can be called
    // (Initial is guaranteed, others may follow)
    
    // Do some stuff...
    token1.Dispose(); // Stop listening for collections
    
    
    
    // Now for the models themselves. For reference I will show how to pass custom args:
    TokenModel token2 = await client.SubscribeModel<Book>(
                  "library.book.1", InitialModel, book => { ChangedModel(1, book); });
    
    // Do some stuff...
    token2.Dispose(); // Stop listening for model changes
    
    
    // Let us call a server command (for example adding new resource).
    // Note that Resgate allows call to return subscribed resource. Therefore strong care must be taken
    // (with Back-End guy) to get the correct call type.
    
    // First, simple call that will ignore the result
    await client.Call("library.books", "new", new Book { title = "Earthsea", author = "Ursula LeGuin" });
    
    // Next call, that can actually subscribe result as model (for example you expect it will return created object)
    TokenModel token3 = await client.CallForModel<Book>("library.books", "add",
         new Book { title = "Earthsea", author = "Ursula LeGuin" } InitialModel, book => { ChangedModel(1, book); });
        
    // And analogous for collections:
    TokenCollection token4 = await client.CallForCollection<Book>("library.books", "get_some",
                           new[] { "param", "foobar" }, Initial, Added, Changed, Removed);
                            
    // And some last ones for custom payloads:
    JToken payload = await client.CallForRawPayload("library.books", "method", new[] { "Sample" } );
    
    // The same, but payload as serialized JSON string:
    string payloadStr = await client.CallForStringPayload("library.books", "method", new[] { "Sample" } );
    
    // The same, but payload as deserialized object:
    Book payloadBook = await client.CallForPayload<Book>("library.books", "method", new[] { "Sample" } );
    
    // Auth methods contain the same variants as call methods, but beware - in case of reconnection
    // they must be called again (protocol is stateless between connections!)
    
    // Therefore you can use this trick:

    TokenReconnected tokenAuth = null;
    bool isAuthenticated = false;
    
    for (;;)
    {
        Console.WriteLine("Enter password:");
        string pwd = Console.ReadLine();
        tokenAuth?.Dispose();
        tokenAuth = await client.AuthAction(async () =>
        {
            isAuthenticated = false;
            try
            {
                await client.Auth("passwd", "login", new Auth {password = pwd});
                isAuthenticated = true;
            }
            catch (ErrorException error)
            {
                Console.WriteLine("Server returned error code: " + error.Message);
            }
        });
        if (isAuthenticated) break;
    }
    // Logout after pressing a key
    Console.ReadKey(true);
    tokenAuth?.Dispose();
    tokenAuth = null;
    isAuthenticated = false;
    await client.Auth("passwd", "logout", null);
}

List<Book> data;

void Initial(List<Book> books)
{
    data = books;
    Console.WriteLine("Initial state:");
    foreach (var book in books)
    {
        Console.WriteLine(book.title + " by " + book.author);
    }
}

void Added(int index, Book book)
{
    Console.WriteLine("Added: " + book.title + " by " + book.author);
    data.Insert(index, book);
}

void Changed(int index, Book book)
{
    var prev = data[index];
    Console.WriteLine("Changed: " + prev.title + " by " + prev.author + " into " + book.title + " by " +
                      book.author);
    data[index] = book;
}

void Removed(int index)
{
    var book = data[index];
    Console.WriteLine("Removed: " + book.title + " by " + book.author);
    data.RemoveAt(index);
}

void InitialModel(Book book)
{
    Console.WriteLine("Initial state of this book is: " + book.title + " by " + book.author);
}

void ChangedModel(int item, Book book)
{
    Console.WriteLine("Book " + item + " changed to: " + book.title + " by " + book.author);
}

resgateclientnet's People

Contributors

shelim avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar

resgateclientnet's Issues

Example1 project contains local paths

Issue

Example1/Example1.csproj contains references to local ResGateClient folder.

Solution

Deleting the ________ResGateClient\ parts made it run without a problem.

And the example worked nicely. Awesome library!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.