5

If JSON arrays are used in a SenseNet settings object, they are not accessible via the OData API.

For example, consider the following SenseNet settings object, which comes installed at Root/System/Settings/Portal.settings by default:

{
    ClientCacheHeaders: [
        { ContentType: "PreviewImage", MaxAge: 1 },
        { Extension: "jpeg", MaxAge: 604800 },
        { Extension: "gif", MaxAge: 604800 },
        { Extension: "jpg", MaxAge: 604800 },
        { Extension: "png", MaxAge: 604800 },
        { Extension: "swf", MaxAge: 604800 },
        { Extension: "css", MaxAge: 600 },
        { Extension: "js", MaxAge: 600 }
    ],
    UploadFileExtensions: {
        "jpg": "Image",
        "jpeg": "Image",
        "gif": "Image",
        "png": "Image",
        "bmp": "Image",
        "svg": "Image",
        "svgz": "Image",
        "tif": "Image",
        "tiff": "Image",
        "xaml": "WorkflowDefinition",
        "DefaultContentType": "File"
    },
    BinaryHandlerClientCacheMaxAge: 600,
    PermittedAppsWithoutOpenPermission: "Details"
}

When viewing this object through the OData API, the ClientCacheHeaders field is not included:

{
    "d": {
        "UploadFileExtensions.jpg": "Image",
        "UploadFileExtensions.jpeg": "Image",
        "UploadFileExtensions.gif": "Image",
        "UploadFileExtensions.png": "Image",
        "UploadFileExtensions.bmp": "Image",
        "UploadFileExtensions.svg": "Image",
        "UploadFileExtensions.svgz": "Image",
        "UploadFileExtensions.tif": "Image",
        "UploadFileExtensions.tiff": "Image",
        "UploadFileExtensions.xaml": "WorkflowDefinition",
        "UploadFileExtensions.DefaultContentType": "File",
        "BinaryHandlerClientCacheMaxAge": 600,
        "PermittedAppsWithoutOpenPermission": "Details",
    }
}

If you search specifically for the ClientCacheHeaders field using the following query:

Odata.svc/Root/System/Settings('Portal.settings')?&metadata=no&$select=ClientCacheHeaders

the API returns null:

{
    "d": {
        "ClientCacheHeaders": null
    }
}

I know that JSON arrays are allowed in settings files because the above example is referenced in the SenseNet wiki page describing settings usage.

Am I performing my OData query incorrectly, or is this some sort of parsing bug in the SenseNet API?

2 Answers2

3

Here's an implementation of the custom OData function suggested by Miklos. Once this is done, you have to register the OData call as described here.

public static class OData
{
    [ODataFunction]
    public static string GetMySettings(Content content)
    {
        var retstr = "";
        try
        {
            var settingsFile = Settings.GetSettingsByName<Settings>("MySettings", content.Path);
            var node = Node.LoadNode(settingsFile.Path) as Settings;
            var bindata = node.GetBinary("Binary");

            using (var sr = bindata.GetStream())
            using (var tr = new System.IO.StreamReader(sr))
                retstr = tr.ReadToEnd();
        }
        catch (Exception e)
        {
            SnLog.WriteException(e);
        }

        return retstr; 
    }
}
Thane Plummer
  • 7,966
  • 3
  • 26
  • 30
2

This is a limitation of the current dynamic json field conversion behind the odata api. It actually converts these setting json properties to sensenet fields, so what you see in the odata response is not the actual settings json, but only the fragments that can be converted to sensenet fields (for the curious: it happens in the JsonDynamicFieldHelper class, BuildDynamicFieldMetadata method).

And unfortunately there is no built-in field type in sensenet for handling json arrays, it is not possible to convert a json array to a field value, this is why the system skips it.

Workaround 1

Get the raw settings json in javascript in two steps. The following request gives you the binary field's direct url:

/odata.svc/Root/System/Settings('Portal.settings')?&metadata=no&$select=Binary

...something like this:

/binaryhandler.ashx?nodeid=1084&propertyname=Binary&checksum=1344168

...and if you load that, you'll get the full raw json, including the array.

Please note: Settings are not accessible to visitors by default, for a reason: they may contain sensitive information. So if you want to let your users access settings directly (the way you tried or the way described in the first workaround above), you'll have to give open permission for the necessary user groups on those setting files. This is not the case with the second workaround.

Workaround 2

Create a custom odata action that returns settings in a format of your choice from the server. This is a better solution, because this way you control which parts of a setting file is actually accessible to the client.

Miklós Tóth
  • 1,490
  • 13
  • 19