question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Global resource-specific metadata

See original GitHub issue

DESCRIPTION

As of today, there are two ways to define metadata. Either global (once per response) or per resource (for each item in the result the metadata is added).

If we add the metadata per resource we can easily gather additional information about the entity by accessing the generic type information via reflection. Unfortunately this seems not possible if using the global metadata, because the interface IResponseMeta is lacking the type information.

ACTUAL BEHAVIOR

Consider the following entity, which contains additional attributes which are used to generate meta data.

public sealed class SupportTicket : Identifiable
{
    [Attr]
    [Required]
    [MaxLength(200)]
    public string Description { get; set; }
}

The only way to include those metadata is by creating a ResourceDefinition inherit from JsonApiResourceDefinition<SupportTicket> which then allows us to override IDictionary<string, object> GetMeta(SupportTicket resource). This allows us to create something like this:

{
    "links": {
        "self": "http://localhost/supportTickets",
        "first": "http://localhost/supportTickets"
    },
    "data": [
        {
            "type": "supportTickets",
            "id": "1",
            "attributes": {
                "description": "Critical: Quae magnam est modi quaerat voluptas repellendus quos dolorem. Ipsum rerum voluptatem facere. Veniam dolor soluta repudiandae doloribus. Qui ratione soluta velit deleniti atque id ad dicta sint."
            },
            "links": {
                "self": "http://localhost/supportTickets/1"
            },
            "meta": {
                "rules": [
                    "required": "true",
                    "maxLength": "200" 
                ]
            }
        }, {
            "type": "supportTickets",
            "id": "2",
            "attributes": {
                "description": "Lorem ipsum dolor sit....."
            },
            "links": {
                "self": "http://localhost/supportTickets/2"
            },
            "meta": {
                "rules": [
                    "required": "true",
                    "maxLength": "200" 
                ]
            }
        }
    ]
}

Even though this generally works, the data sent to the client is highly redundant.

EXPECTED BEHAVIOR

We need a way to create entity related global meta data which leads to the following result:

{
    "links": {
        "self": "http://localhost/supportTickets",
        "first": "http://localhost/supportTickets",
        "meta": {
            "rules": [
                "required": "true",
                "maxLength": "200" 
            ]
        }
    },
    "data": [
        {
            "type": "supportTickets",
            "id": "1",
            "attributes": {
                "description": "Critical: Quae magnam est modi quaerat voluptas repellendus quos dolorem. Ipsum rerum voluptatem facere. Veniam dolor soluta repudiandae doloribus. Qui ratione soluta velit deleniti atque id ad dicta sint."
            },
            "links": {
                "self": "http://localhost/supportTickets/1"
            }
        }, {
            "type": "supportTickets",
            "id": "2",
            "attributes": {
                "description": "Lorem ipsum dolor sit....."
            },
            "links": {
                "self": "http://localhost/supportTickets/2"
            }
        }
    ]
}

For some reason this feature seemed to be remove in PR: https://github.com/json-api-dotnet/JsonApiDotNetCore/pull/845/files

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
bart-degreedcommented, May 10, 2021

If I understand you correctly, you’d like to add top-level meta to GET resource requests that lists the attr validation rules for the resource type being requested. To accomplish that, inject IJsonApiRequest in your IResponseMeta implementation and make sure to register it request-scoped.

Example:

public sealed class SupportTicket : Identifiable
{
    [Attr]
    [Required]
    [MaxLength(100)]
    public string Description { get; set; }

    [Attr]
    [MaxLength(25)]
    public string Other { get; set; }
}

public sealed class SupportResponseMeta : IResponseMeta
{
    private readonly IJsonApiRequest _request;

    public SupportResponseMeta(IJsonApiRequest request)
    {
        _request = request;
    }

    public IReadOnlyDictionary<string, object> GetMeta()
    {
        if (!_request.IsReadOnly || _request.Kind == EndpointKind.Relationship)
        {
            return null;
        }

        IDictionary<string, IDictionary<string, string>> rules = new Dictionary<string, IDictionary<string, string>>();

        ResourceContext resourceContext = _request.SecondaryResource ?? _request.PrimaryResource;

        foreach (AttrAttribute attrAttribute in resourceContext.Attributes)
        {
            IDictionary<string, string> attributeRules = GetAttributeRules(attrAttribute);

            if (attributeRules.Any())
            {
                rules.Add(attrAttribute.PublicName, attributeRules);
            }
        }

        return rules.Any()
            ? new Dictionary<string, object>
            {
                ["rules"] = rules
            }
            : null;
    }

    private static IDictionary<string, string> GetAttributeRules(AttrAttribute attrAttribute)
    {
        var attributeRules = new Dictionary<string, string>();

        foreach (Attribute attribute in attrAttribute.Property.GetCustomAttributes())
        {
            string ruleName = null;
            string ruleValue = null;

            if (attribute is RequiredAttribute)
            {
                ruleName = "required";
                ruleValue = "true";
            }
            else if (attribute is MaxLengthAttribute maxLengthAttribute)
            {
                ruleName = "maxLength";
                ruleValue = maxLengthAttribute.Length.ToString();
            }
            // ...

            if (ruleName != null)
            {
                attributeRules.Add(ruleName, ruleValue);
            }
        }

        return attributeRules;
    }
}

which produces:

{
  "meta": {
    "rules": {
      "description": {
        "required": "true",
        "maxLength": "100"
      },
      "other": {
        "maxLength": "25"
      }
    }
  },
  "links": {
    "self": "http://localhost/supportTickets",
    "first": "http://localhost/supportTickets"
  },
  "data": []
}
0reactions
bart-degreedcommented, May 10, 2021

The general hint was added to the docs recently, but it hasn’t been merged yet. See https://github.com/json-api-dotnet/JsonApiDotNetCore/blob/write-callbacks/docs/usage/extensibility/middleware.md.

Read more comments on GitHub >

github_iconTop Results From Across the Web

[Salesforce Metadata] Global Resource Property
A value of 3 or greater and 3600 or smaller may be specified. Number of the Retrieve monitorings performed, Required, Only environment variables...
Read more >
Global metadata
Global metadata ¶. Global metadata is metadata that is not associated with any item or collection. It can primarily be used as a...
Read more >
Global, regional, and zonal resources | Compute Engine ...
This document describes global, regional, and zonal Compute Engine resources. Google Cloud resources are hosted in multiple locations worldwide.
Read more >
Link metadata to related resources using global data links
Global data links let you link metadata displayed in Splunk Observability Cloud to the following relevant resources:.
Read more >
MetadataException: Unable to load the specified metadata ...
csdl, .ssdl and .msl files. When the resources have different names to the ones specified in the metadata value, it's not going to...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found