B1SLayer .NET Client

repository·dev·Indexed 41 days ago

https://github.com/bgmulinari/b1slayer

A lightweight .NET client for the SAP Business One Service Layer. It provides fluent request building, automatic session management, and automatic retries for GET, POST, PATCH, and DELETE operations, including support for batch requests and file updates.

Tokens
1.7K
Snippets
6
Records
6
Agent score
2%

What's inside B1SLayer

  1. Execute Batch Requests

    dev

    You can perform multiple operations in a single HTTP request using SLBatchRequest. This is highly efficient for reducing network round-trips.

    1. Create SLBatchRequest objects specifying the HttpMethod, the resource path, and the payload.
    2. Use .WithReturnNoContent() if you want to add the Prefer: return-no-content header.
    3. Pass the requests to serviceLayer.PostBatchAsync(...) to execute them.

    Returns an array of HttpResponseMessage objects representing the result of each operation.

    var req1 = new SLBatchRequest(
        HttpMethod.Post, 
        "BusinessPartners", 
        new { CardCode = "C00001", CardName = "I'm a new BP" }) 
        .WithReturnNoContent();
    
    var req2 = new SLBatchRequest(HttpMethod.Patch,
        "BusinessPartners('C00001')",
        new { CardName = "This is my updated name" });
    
    var req3 = new SLBatchRequest(HttpMethod.Delete, "BusinessPartners('C00001')");
    
    HttpResponseMessage[] batchResult = await serviceLayer.PostBatchAsync(req1, req2, req3);
  2. Perform POST, PATCH, and DELETE requests

    dev

    B1SLayer supports standard CRUD operations via fluent API calls.

    POST (Create)

    Use .PostAsync<T>(object) to send a JSON body to a resource. The provided object is serialized to JSON, and the response is deserialized into the specified type T.

    PATCH (Update)

    • JSON Update: Use .PatchAsync(object) to update specific fields using an anonymous object or a model.
    • File Update: Use .PatchWithFileAsync(string path) to update or add an item image or other file-based resource.

    DELETE

    Batch requests can include HttpMethod.Delete to remove resources.

    // POST a new order
    var createdOrder = await serviceLayer.Request("Orders").PostAsync<MyOrderModel>(myNewOrderObject);
    
    // PATCH a Business Partner name
    await serviceLayer.Request("BusinessPartners", "C00001")
        .PatchAsync(new { CardName = "Updated BP name" });
    
    // PATCH an item image file
    await serviceLayer.Request("ItemImages", "A00001")
        .PatchWithFileAsync(@"C:\ItemImages\A00001.jpg");
    
    // POST an attachment
    var attachmentEntry = await serviceLayer.PostAttachmentAsync(@"C:\files\myfile.pdf");
  3. Initialize an SLConnection

    dev

    The SLConnection object is the central entry point for all Service Layer requests and session management.

    Key usage rules:

    • Use only one instance per company/user across your entire application.
    • If you need to connect to multiple databases or use different users, create multiple instances.
    • No manual login required: The session is managed automatically and renewed whenever necessary.

    Constructor parameters:

    • baseUrl: The Service Layer URL (e.g., https://sapserver:50000/b1s/v1).
    • companyDb: The name of the Company Database.
    • username: The Service Layer username.
    • password: The Service Layer password.
    var serviceLayer = new SLConnection("https://sapserver:50000/b1s/v1", "CompanyDB", "manager", "12345");
  4. Perform GET requests with B1SLayer

    dev

    B1SLayer provides fluent methods to perform GET requests on specific resources, supporting filtering, selection, and pagination.

    Get a single record by ID

    Use .Request(resource, id).GetAsync<T>() to fetch a record and deserialize it into a custom model.

    Get a list with query parameters

    You can chain methods to build complex queries:

    • .Filter(string): Adds a Service Layer filter (e.g., startswith(...)).
    • .Select(string): Specifies which fields to return.
    • .OrderBy(string): Specifies the sort order.
    • .WithPageSize(int): Sets the page size.
    • .WithCaseInsensitive(): Enables case-insensitive searching.

    Get all records

    Use .GetAllAsync<T>() to perform multiple GET requests until all entities in the database are retrieved. This method automatically unwraps the result from the Service Layer's 'value' array.

    // Get single record
    var order = await serviceLayer.Request("Orders", 823).GetAsync<MyOrderModel>();
    
    // Get filtered list
    var bpList = await serviceLayer.Request("BusinessPartners")
        .Filter("startswith(CardCode, 'c')")
        .Select("CardCode, CardName")
        .OrderBy("CardName")
        .WithPageSize(50)
        .WithCaseInsensitive()
        .GetAsync<List<MyBusinessPartnerModel>>();
    
    // Get all records
    var allItemsList = await serviceLayer.Request("Items").GetAllAsync<MyItemModel>();
    
    // Get via composite key
    var altCatNum = await serviceLayer
        .Request("AlternateCatNum(ItemCode='A00001',CardCode='C00001',Substitute='BP01')")
        .GetAsync<MyAltCatModel>();