Web API in detail

You can consume API services in a RESTful manner via HTTPS calls by using HTTPS methods:

  • GET: Get the resource.

  • POST: Create a new resource.

  • PUT: Update the existing resource.

  • PATCH: Update a part of the existing resource.

  • DELETE: Remove the resource.

OData query options (such a $expand, $filter, $top, $select, etc.) and API specific options (such as SmApiFulfillCountry) can be passed via query strings.

Paging is required if you want to query multiple records. You can do this with the OData query options $skip and $top. The maximum value for $top is returned in the Smartstore-Api-MaxTop header field. This value is configurable by the store owner.

Due to Basic Authentication, it is mandatory to send requests via HTTPS. HTTP will return a 421 Misdirected Request status code. The only exception is that developers can send requests via HTTP to their local development environment.

A request body must be UTF-8 encoded.

Request HTTP header fields

Name: value
Required
Remarks

Accept: application/json

yes

Only application/json is valid.

Accept-Charset: UTF-8

yes

Authorization: Basic <key pair>

yes

Prefer: return=representation

no

Can be sent for PUT and PATCH requests if the API should answer with status code 200 and entity content response, otherwise 204 No Content is returned.

Response HTTP header fields

Name: example value
Description

Smartstore-Api-AppVersion: 5.1.0.0

Smartstore version used by the store.

Smartstore-Api-Version: 1 5.0

The highest API version supported by the server (unsigned integer) and the version of the installed API module (floating-point value).

Smartstore-Api-MaxTop: 120

The maximum value for OData $top query option. The default value is 120 and is configurable by store owner.

Smartstore-Api-Date: 2022-11-11T14:35:33.7772907Z

The current server date and time in ISO-8601 UTC.

Smartstore-Api-CustomerId: 1234

The customer identifier of the authenticated API user. Returned only if authentication is successful.

Smartstore-Api-AuthResultId: 5

The ID of the reason why the request was denied. Returned only if the authentication failed.

See authentication.

Smartstore-Api-AuthResultDesc: UserDisabled

A short description of the reason why the request was denied. Returned only if the authentication failed.

See authentication.

WWW-Authenticate: Basic realm="Smartstore.WebApi", charset="UTF-8"

The name of the failed authentication method.

Query options

OData query options allow manipulation of data queries like sorting, filtering, paging etc. They are sent in the query string of the request URL.

Custom query options should make the Smartstore Web API easier to use, especially when working with entity relationships.

SmApiFulfill{property_name}

Entities often have multiple relationships with other entities. In most cases, an ID must be set to create or modify them. But often you do not know the ID. To reduce the number of API round trips, this option can set an entity relationship indirectly.

For example, imagine you want to add a German address, but you don't have the ID of the German country entity, required for address insertion. Instead of calling the API again to get the ID, you can add the query option SmApiFulfillCountry=DE and the API will automatically resolve the relationship.

The API can fulfill the following properties:

Entity property
Expected query value
Query string example

Country

The two or three letter ISO country code.

SmApiFulfillCountry=USA

StateProvince

The abbreviation of a state or province.

SmApiFulfillStateProvince=CA

Language

The culture of a language.

SmApiFulfillLanguage=de-DE

Currency

The ISO code of a currency.

SmApiFulfillCurrency=EUR

Web API and modules

If a module extends the domain model with its own entities, these can also be integrated into the Web API using ODataModelProviderBase or IODataModelProvider. This allows the module developer to make their entities externally accessible without having to create their own Web API.

The Smartstore.Blog module registers two entities BlogComment and BlogPost through the ODataModelBuilder using the following BlogODataModelProvider.

internal class BlogODataModelProvider : ODataModelProviderBase
{
    public override void Build(ODataModelBuilder builder, int version)
    {
        builder.EntitySet<BlogComment>("BlogComments");
        builder.EntitySet<BlogPost>("BlogPosts");
    }

    public override Stream GetXmlCommentsStream(IApplicationContext appContext)
        => GetModuleXmlCommentsStream(appContext, "Smartstore.Blog");
}

Use plural for the name of the entity set. For example, BlogComments, not BlogComment.

Next, you need to add an API controller for each entity. It is recommended that you create a subfolder called Api in the controller folder of the module. Inherit your controller from WebApiController, as shown in the example.

/// <summary>
/// The endpoint for operations on the BlogComment entity.
/// </summary>
public class BlogCommentsController : WebApiController<BlogComment>
{
    [HttpGet("BlogComments"), ApiQueryable]
    [Permission(BlogPermissions.Read)]
    public IQueryable<BlogComment> Get()
    {
        var query = Db.CustomerContent
            .AsNoTracking()
            .OrderByDescending(x => x.CreatedOnUtc)
            .OfType<BlogComment>();

        return query;
    }

    [HttpGet("BlogComments({key})"), ApiQueryable]
    [Permission(BlogPermissions.Read)]
    public SingleResult<BlogComment> Get(int key)
    {
        return GetById(key);
    }

    [HttpGet("BlogComments({key})/BlogPost"), ApiQueryable]
    [Permission(BlogPermissions.Read)]
    public SingleResult<BlogPost> GetBlogPost(int key)
    {
        return GetRelatedEntity(key, x => x.BlogPost);
    }

    [HttpPost]
    [Permission(BlogPermissions.Create)]
    public async Task<IActionResult> Post([FromBody] BlogComment entity)
    {
        return await PostAsync(entity);
    }

    [HttpPut]
    [Permission(BlogPermissions.Update)]
    public async Task<IActionResult> Put(int key, Delta<BlogComment> model)
    {
        return await PutAsync(key, model);
    }

    [HttpPatch]
    [Permission(BlogPermissions.Update)]
    public async Task<IActionResult> Patch(int key, Delta<BlogComment> model)
    {
        return await PatchAsync(key, model);
    }

    [HttpDelete]
    [Permission(BlogPermissions.Delete)]
    public async Task<IActionResult> Delete(int key)
    {
        return await DeleteAsync(key);
    }
}

Use theSmartstore.Web.Api.Controllers namespace for all Web API controllers!

The BlogCommentsController defines OData Web API endpoints to get, create, update, patch (partially update), and delete blog comments. It also defines an endpoint to get the associated blog post through the BlogPost navigation property. See the Web API module controllers for more endpoint definitions.

Override ODataModelProviderBase.GetXmlCommentsStream to automatically include your code comments in the Swagger documentation of the Web API. To do this, the Documentation File option must also be enabled in the module project settings. The path to the XML documentation file should be left empty. This will export your code comments to an XML file with the same name as the module at compile time (Smartstore.Blog.xml in the example above), which will then be used by the Web API.

Last updated

Was this helpful?