Giter Club home page Giter Club logo

sn-client-dotnet's Introduction

Welcome to sensenet

sensenet is a content repository with API first approach packed with a full featured permission system, preview and collaboration tools.

Join the chat at https://gitter.im/SenseNet/sensenet

A basic setup of sensenet has three top-level parts:

  • A content repository that is the storage and service layer
  • An application that uses the content of the connected content repository through API calls
  • A sensenet admin surface (only in SNaaS) that helps you carry out common content management tasks

SNaaS architecture

Everything is content

Content is the basic block for storing information in sensenet. A content can be any kind of data, user, document, workspace, memo, task, and more. Using content items everywhere unlocks a great deal of exceptional features, making your experience as a user more seamless, and your job as a developer a lot easier.

Licensing

SNaaS (sensenet as a service)

In this model, sensenet content repositories live in our cloud infrastructure.

Advantages

  • no installation required (easy onboarding)
  • patches and upgrades are taken care of by us
  • no hosting related tasks
  • central admin surface
  • flexible pricing plans (based on # of contents, requests, and users)

on-prem

For the terms of on-prem licensing please contact our sales team.

Resources

Check out the links below to get further information:

Contributing

All kinds of contributions are welcome! We are happy if you have an idea, bugfix or feature request to share with others. Please check out our Contribution guide for details.

sn-client-dotnet's People

Contributors

drwatson1 avatar eduherminio avatar f1x3d avatar gitter-badger avatar hashtagnulla avatar herflis avatar huszerlbence avatar kavics avatar mrcll avatar thiagobfiorenza avatar tusmester avatar vargajoe avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

sn-client-dotnet's Issues

Parse html server error messages

Currently we handle only json error messages that come from the server. We have to at least try to parse the error if it is a html response and extract useful information if possible.

Client authentication

We want to add support for a modern authentication process in the sensenet client. The easiest way to do that is to add IdentityServer4 support.

Required package reference: IdentityModel

Requirements

  • authentication is server-specific, not a global setting
  • no breaking change, the previous login api and auth workflow should still work (basic or NTLM auth)
  • hide token refresh mechanism from callers (client developers), that should be done automatically by the client library internally
  • the client library itself does not save/serialize token data and cookies, only handles in-memory info
  • the caller should be able to get and set all auth data in a serializable format (so that users do not have to give their un/pw every time they start the client app)

Add API key as an authentication method in the .net client

Currently only the client/secret authentication method is supported by the client API. As a developer I would like to provide an API key instead of a client/secret so that I can use the library in more scenarios.

The client should send the provided api key with every request the same way as with the current access token solution.

  • extends the current ServerContext api
  • works from configuration
  • works form api calls (meaning usable from tools like snio)

Token authentication

Add an initial token support to the client library.

  • store access and refresh tokens in a connection
  • use the access token when sending a request if filled

In this basic solution it is the responsibility of the client application to keep track of expiration dates and refreshing the access token when necessary (in a background operation).

Strongly typed client models

Scenario: get content from sensenet and convert it to a model and pass it on to the client.

This issue is about providing best practices and possibly a reusable code or client API for converting general dynamic content objects into custom models that can be used by the business logic or passed down to the client of an Asp.Net app.

  • can we automatize type conversion?
  • what about different content types (schemas)?
  • what about field types, for example reference fields?

Error when using Content.UploadAsync to upload file with chinese file name

I'm trying to upload file with Chinese file name to sensenet using Content.UploadAsync. For some file names, such as 运维管理.txt , there is an exception "Specified value has invalid Control characters. Parameter name: value". If rename to another file name, maybe it works well. Seems like encode issue. Could you give me some suggestions?

I'm trying to upload file with Chinese file name to sensenet using Content.UploadAsync. For some file names, such as 运维管理.txt , there is an exception "Specified value has invalid Control characters. Parameter name: value". If rename to another file name, maybe it works well. Seems like encode issue. Could you give me some suggestions?

My code:

using (var stream = new FileStream(localFilePath, FileMode.Open))
{
await Content.UploadAsync(parentPath, fileName, stream, "File");
}
StackTrace:

at System.Net.WebHeaderCollection.CheckBadChars(String name, Boolean isHeaderValue)
at System.Net.WebHeaderCollection.Add(String name, String value)
at SenseNet.Client.RESTCaller.CreateChunkUploadWebRequest(String url, ServerContext server, UploadData uploadData, String boundary, Stream& requestStream) in sn-client-dotnet-master\sn-client-dotnet-master\src\SenseNet.Client\RESTCaller.cs:line 620
at SenseNet.Client.RESTCaller.d__23.MoveNext() in sn-client-dotnet-master\sn-client-dotnet-master\src\SenseNet.Client\RESTCaller.cs:line 490

Get current user data

Create a dedicated API for loading the currently logged in user from a repository service.
No special server-side API is needed, it is enough to provide information about the user that is in the token contained in the request.

Upload/download through the Repository API

Port the current static upload/download methods from the Content and RestCaller classes to the new IRepository interface (or to the Content class if that is more logical).

[.Net client] LoadReferences cannot parse a single reference field

When we call the LoadReferencesAsync method on a single reference field (e.g. CreatedBy ) it fails with the following error:

Cannot convert type 'Newtonsoft.Json.Linq.JObject' to 'Newtonsoft.Json.Linq.JArray'

We have to parse single reference fields differently and return a list containing a single item.
Additionally we may also add a new convenience method for cases when the caller knows that the result is singular: LoadReferenceAsync that returns a single content instead of a list.

Retrier in .Net client

Integrate the Retrier service into the .Net client Content API. The goal is to retry operations that throw well-known exceptions automatically, without the caller knowing.

Incorrect Server parameter handling

In some cases the static Content API does not pass the provided server parameter correctly to the underlying infrastructure. This cases the system trying to access the default server instance which does not always exists.

Solution

When a method gets a server parameter, pass that in the constructor of the ODataRequest object so that the server url can be determined correctly.

Refactor the client security API

Review the security (permissions management) API in the client and build a new one on the new repository instance API if necessary.

Repository API: LINQ for sensenet

Provide a LINQ implementation over the repository on the client side.

repository. Where(c => c.InTree("/Root/Content") && c.TypeIs("Article"))...
repository. Count(...)
repository. Any(...)

Repository API: custom request

Extend the new repository API with method(s) for executing a manual/custom odata request with all the possible options. For example GetResponseStringAsync, GetResponseJsonAsync.

  • consolidate many RestCaller methods to a smaller API
  • every method should:
    • expect a cancellation token
    • use the _retrier instance to automatically retry the operation
  • old methods on Content (and RestCaller?) should become obsolete

Content operations is a separate issue: #98

[Authentication] Token store for multiple servers

We need a token store that is able to find the authority and get tokens from it. The API should require only the repository url and the credentials (client/secret) for authentication.

In this first phase we do not want to handle token refresh, that is a different issue: #44

Unable to Upload File

Hi,

I'm trying to upload file to Sensent (Local Machine Instance) through Sensenet .Net Client. But while calling the method

return await UploadInternalAsync(binaryStream, uploadData, requestData, server, progressCallback);
getting issue like assembly reference not found,
'Could not load file or assembly 'SenseNet.Tools, Version=3.1.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.'

Could you please help me to resolve this issue. Because the assembly 'SenseNet.Tools' is already exists in my project as well as its up to date.

Please find one more issue(http://server/Root/System/SystemPlugins/Portlets/IntraUploadDialog.ascx(80): error CS0103: The name 'BlobStorageConfiguration' does not exist in the current context) I'm facing while trying to upload file from Screen level. Please find the snapshot attached below.
sensenet_upload_issue

Installation on Live Server

HI Team,
Goo Morning,

I was trying to install sensenet community edition on my live server by following the steps mentioned on this wiki page.

http://wiki.sensenet.com/How_to_install_Sense/Net_from_web_deployment_package_(IIS_7.5_and_IIS_7.0)

At step 1, I have downloaded the zip file. When I have extracted the zip file to a folder. I don't see the any source folder.

Web Deployment

And also I have tried to setup/install using Web Deployment. As shown in Step 8 the options are not avaialble. I am just seeing json files and issues.

[BUG] fields against values of equality, very bad!

SaveAsync throws exception on contents having a field value with equal sign (=).

For example try to set a link with url parameters in any text type fields and it says:
The server returned an error (HttpStatus: InternalServerError): Invalid character after parsing property name. Expected : but got: N. Path , line 1, position 5.

on version 2.0.7

ODataRequest should work with a local server variable too.

Currently when we create an ODataRequest object without configuring a default Server first, it throws an exception. This is too strict because it does not support scenarios when there is no single server but multiple servers that need to be accessed dynamically.

Solution

ODataRequest should take a server parameter and use its url to build itself.

Expose field names found in the response

We need the available field names on the content so that we can enumerate field values. This is not about having a full schema map, just the fields that can be found in the response.

Duplicate parameter in ODataRequest

The ODataRequest object is responsible for converting itself to a url string. During this process we fill a dictionary with parameters. If there is a duplicate parameter (e.g. the caller provided the metadata parameter that we also want to set), an exception is thrown.

foreach (var key in Parameters.Keys)

Hint: use dictionary indexer instead of Add, but make sure the precedence is correct.

  • precedence: method parameter overrides the property
  • add test

Error when uploading a file (version 2.0.5)

An error occures when calling the upload api in version 2.0.5 the following way:

await SenseNet.Client.Content.UploadAsync("/Root/Contents/ParentFolder", metaDataObject.FileName, stream, "File");

Error:

'Value cannot be null.\nParameter name: path2' SenseNet.Client.ClientException: Value cannot be null.\nParameter name: path2
   at SenseNet.Client.RESTCaller.ProcessWebRequestResponseAsync(String url, HttpMethod method, ServerContext server, Action`3 requestProcessor, Action`1 responseProcessor, CancellationToken cancellationToken)
   at SenseNet.Client.RESTCaller.ProcessWebResponseAsync(String url, HttpMethod method, ServerContext server, HttpContent httpContent, Action`1 responseProcessor, CancellationToken cancellationToken)
   at SenseNet.Client.RESTCaller.UploadInternalAsync(Stream binaryStream, UploadData uploadData, ODataRequest requestData, ServerContext server, Action`1 progressCallback)
   at SenseNet.Client.RESTCaller.UploadAsync(Stream binaryStream, UploadData uploadData, String parentPath, ServerContext server, Action`1 progressCallback)
   at SenseNet.Client.Content.UploadAsync(String parentPath, String fileName, Stream stream, String contentType, String propertyName, ServerContext server, Action`1 progressCallback)
   at IktatoWeb.Controllers.UploaderController.UploadChunk(IFormFile file, String dzuuid, String dzchunkindex, String dztotalchunkcount, String dztotalfilesize, String filename, String filetype) in d:\DevBS\Iktato\src\IktatoWeb\Controllers\UploaderController.cs:line 89

Downgrading to version 2.0.4 solves the issue according to @blaskodaniel.

Initial Repository service API in .Net client

Create the new Repository API that

  • works with the DI container (acquired by GetService)
  • lets developers authenticate easily (using configuration and maybe an init method)
  • API for loading (instantiating) content items. In the future: custom business types.
  • compatible with the legacy API

The purpose of this refactor is to provide developers an easy way to manage content items without having to worry about authentication or services. Content items should be self-supported, they should know about their repository and get all the necessary services from the DI container.

Authenticate using an access token

This story is part of an effort to make the following scenario simpler: the .Net client is used on a backend Asp.Net server to make server-to-server calls to a separate repository service.

There is a use case when a user authenticates in their browser, sends a token to the custom backend app (usually an Asp.Net app) and we need to connect to a separate sensenet repository service using that token - in the name of the authenticated user, not as a technical admin.

In the previous API we already solved this: #70

Now we need to extend the new Repository API with a possibility to provide an access token and execute requests in the name of the user represented by the token.

Proposal

Extend the RepositoryCollection API with a new overload of the GetRepositoryAsync method that takes a token (or an AuthenticationInfo) parameter:

public async Task<IRepository> GetRepositoryAsync(string name, AuthenticationInfo authInfo, CancellationToken cancel)

This method would load a repository instance constructed specifically for the provided token or api key. This would mean multiple IRepository instances cached for the same sensenet repository but for different users. The cache key currently is the provided name but we could construct a cache key that also includes the api key or the token. The underlying server API already supports providing an access token, no need to rewrite anything.

Trusted certs in dev mode

The web-client needs to trust any server certificate in development mode.
The development mode comes from outside (maybe a get/set "Trusted" property in the Server context...)

Possible memory deadlock at async calls in a server environment

If you use a library (like this sn client) that has an async api in a web server environment, async calls can lead to memory deadlock, if the library does not take care of handling the thread/task context correctly.

Solution: inside the library it is advisable to use the ConfigureAwatit(false) call at the end of every async call. For example:

var customer = await GetCustomerAsync(id).ConfigureAwait(false);

Resources:

.Net client in a server environment

Scenario: the .Net client is used on a backend Asp.Net server to make server-to-server calls to a separate repository service. This epic contains issues to make this scenario simpler to implement.

Authentication token refresh

The client is capable of using an access token, but there is no mechanism for refreshing the access token using the refresh token, if the client is used for a long period of time - e.g. from a web application.

Define a background worker (?) for checking token expiration and refreshing the access token when necessary.

Proposal

We need a token storage that can be used in a web server environment. It should be a black box that handles token refresh operations in the background.

  • automatic token refresh
  • manage tokens by server url (handle multiple servers at the same time)
  • the storage can be put into the usual .Net dependency injection container
    • optionally add helper methods for accessing the container
  • async API

Get server context with custom token

This story is part of an effort to make the following scenario simpler: the .Net client is used on a backend Asp.Net server to make server-to-server calls to a separate repository service.

The current server factory API assumes we always authenticate with the repository using configured (admin) clientid/secret values. There is a new scenario we need to support: when the user logs in on the client and makes a request to the custom backend API, and we need to make backend calls to a sensenet repository service from there in the name of the currently authenticated user.

  • we want to get a server object without authentication
  • because we already have a token that we want to set

Acceptance

  • I can use the same or similar feature service registration API as in other cases (AddSenseNetRepository)
  • get a server context using a similar API (GetServerAsync) and provide a custom auth token

Migrate the .Net Client to Netstandard

Hi there,

Do you have any plans to migrate the sn client to netstandard?

I noticed the steps being taken to migrate the server components. I guess that especially makes sense for the client as it is intended to be incorporated as a component in other applications.

[Client .Net] Add more APIs for calling actions

Add more client APIs for calling content actions. New apis should provide shortcuts (e.g. dedicated actionName parameter instead of a generic ODataRequest parameter).

DISCUSSION: specify the API list before starting to work on this!

  • add missing CancellationToken parameter where it is possible
  • ProcessWebResponse and related methods: add async responseProcessor method param
  • add shortcut methods for POST requests in RESTCaller
  • add object parameter for post data (instead of string)
  • add methods to the Content class static/instance API
    • action requests (GET/POST/PATCH) (with actionName parameter)
    • Exists (with id/path and version (!) parameter) for existence check
    • simplified download (by content id/path, target stream)
    • ...

Add client types for common CTDs

Add or extend client types representing well-known sensenet CTDs. Add their well-known properties and possibly helper methods as well.

  • User
    • membership helpers, for example IsInGroup?
  • Group
    • user management helper methods? AddMember etc.
  • File
    • Download helper(s)?
  • Folder
    • Children helpers?
  • ?

.Net client: Repository instance API

Design a new API that works in a modern DI-oriented environment - instead of the current static Content API.

  • a single Repository service instance that encapsulates:
    • the connection to the repository service (currently ServerContext)
    • authentication
    • content instance creation API, including custom business types (e.g. MyFolder). The goal is to create content items in a way that lets developers inject services easily.
    • load and query API
  • CRUD operations should remain on the Content class
  • Content class can be inherited (custom business objects, see above)
  • all APIs should be async (with cancellation) and trace/log every operation
  • current/legacy APIs should remain intact
  • make the whole static RestCaller class obsolete when this is completed.

Cached invalid repository connection

There are two scenarios.

The good case: The client starts and gets a repository that works correctly. After any network error, the reconnection can be successful and the work can continue.

The worst case: The client starts and gets a repository that does not work correctly because of any reason. Work is impossible, even after a successful connection. There is only one option: the client must be restarted.

The reason: The IRepositoryCollection instance (from the services) caches repositories on first access. An unavailable repository has an empty access token forever, so the only accessible user for it can be the Visitor.

Possible solutions

  • If the client can recognize this problem, it could solve it by invalidating the server cache (e.g. repositories. Reset();) and restart is not necessary.
  • caching repositories for only a limited time in a real memory cache instead of a dictionary
  • cache reset should target a single repository or maybe a server instance, not all of them

Use IHttpClientFactory to avoid socket exhaustion in DefaultRestCaller

We should NOT instantiate HttpClient directly but through the factory that will handle the connection pooling for us.

For details: https://learn.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests

  • see the ProcessWebRequestResponsePrivateAsync method
  • add the Microsoft.Extensions.Http NuGet package
  • add the service using AddHttpClient()
  • inject the IHttpClientFactory service to DefaultRestCaller
  • use it:
using HttpClient client = _httpClientFactory.CreateClient();

[Testing] Modernize tests

Currently many tests in this repository expect an accessible sensenet instance on localhost. Make tests independent and executable in memory locally, without a service dependency.

Query Custom ListFields

+TypeIs:CustomContract +#ContractDeadline:<'2011-09-01 12:00:00'

Execute above contentquery with Content.QueryAsync

        var results = await Content.QueryAsync("+TypeIs:CustomContract +#ContractDeadline:<'2011-09-01 12:00:00''",
            select: new[] { "Id", "Name", "Path", "Type", "DisplayName" },
            expand: new[] { "ModifiedBy" },
            settings: new QuerySettings
            {
                EnableAutofilters = FilterStatus.Enabled,
                Top = 2000
            });

'# fields' don't seem to be queryable

Refactor remaining Content operations to use the new API

Currently there are several instance operations (Delete, CheckOut) on the Content class that use the old RESTCaller static api. Update these methods:

  • create new overloads with cancellation support
  • make them call the IRestCaller instance if available instead of directly calling the static RESTCaller api (this way we get testability and retry automatically). Keep static calls in case of old methods for compatibility reasons.

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.