Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attribute to override rel as convenience for serializing and for disambiguating deserialization #67

Closed
kbrichan opened this issue Jul 22, 2014 · 4 comments

Comments

@kbrichan
Copy link
Collaborator

Let's enhance this project to allow attributing embedded properties with a rel override, such as this:

public class AuthorRepresentation : Representation {
   [Rel("recentPosts")]
   public List<PostResource> RctPosts { get; set; }
   [Rel("popularPosts")]
   public List<PostResource> PopPosts { get; set; }
}

The net result is to output json like this:

{
    "_embedded": {
        "recentPosts": [
            {"someProp1": "someValue1"},
            {"someProp1": "someValue2"}
        ],
        "popularPosts": [
            {"someProp1": "someValue3"},
            {"someProp1": "someValue4"}
        ]
    }
}

The common thing currently is to just have PostResource hardcode its rel to something. So to accomplish the above json with the current implementation without the Rel override attribute, one would have to set the rel of each of the objects in the RctPost list to one rel and the objects in PopPosts to another.

Also, upon deserializing, without the Rel override attribute, the deserializer would have no idea which list to put the incoming PostResource objects into.

@MattRyan
Copy link

Would using the JsonPropertyAttribute be a reasonable implementation?

@wis3guy
Copy link
Collaborator

wis3guy commented Aug 1, 2014

It will not result in the exact same response, but wouldn't a simple solution be to have different resources for the list of posts? I'd imagine you would also want these lists to be accessible through a different uri, ie. ~/posts/recent and ~/posts/popular. You would then set the Rel on the RecentPostsResource and the PopularPostsResource, resulting in:

public class AuthorRepresentation : Representation {
   public RecentPostsResource RctPosts { get; set; }
   public PopularPostsResource PopPosts { get; set; }
}

Again, it will not yield the same output, you will have an extra layer in your embeded resources, but imho it is a cleaner solution.

Just my 2 cents ...

@TradeArcher2020
Copy link

I created an extension method for Representation that will look for a RelAttribute on all properties that are of type Representation and will override the value of the Rel property for that property instance to whatever you set it to in the RelAttribute. Just call the extension method in the override of the CreateHypermedia method.

//Example:

public class MyRep : Representation
{
[Rel("ThisIsAnotherNameForMyEmbeddedObject"]
public AnotherRepresentation SomeOtherRepresentation { get; set; }

protected override void CreateHypermedia()
{
    this.SetAlternateRelsForRepresentationPropertiesFromRelAttribute();
}

}

//Extension Method:

    public static void SetAlternateRelsForRepresentationPropertiesFromRelAttribute(this Representation representation)
    {
        var props =
            representation.GetType()
                .GetPropertiesHierarchical()
                .Where(
                    prop =>
                        prop.PropertyType.IsSubclassOf(typeof(Representation)) &&
                        prop.CustomAttributes.Any(att => att.AttributeType == typeof (RelAttribute)));

        props.ForEach(prop =>
        {
            var propValue = prop.GetValue(representation) as Representation;
            if (propValue != null)
            {
                var relAttribute = prop.GetCustomAttribute<RelAttribute>(true);
                if (relAttribute != null)
                {
                    propValue.Rel = relAttribute.Rel;
                }
            }
        });
    }

//Custom RelAttribute

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class RelAttribute : Attribute
{
    public string Rel { get; private set; }

    public RelAttribute(string rel)
    {
        if (String.IsNullOrEmpty(rel))
            throw new ArgumentException("Parameter 'rel' must not be null or empty.");
        Rel = rel;
    }
}

//Result:
{
_links: {...}
_embedded:{
ThisIsAnotherNameForMyEmbeddedObject: {...}
}
}

@panmanphil
Copy link
Collaborator

closing stale issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants