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

Property System.String String is not included in the context #8

Open
colin-young opened this issue Feb 22, 2017 · 10 comments
Open

Property System.String String is not included in the context #8

colin-young opened this issue Feb 22, 2017 · 10 comments
Assignees

Comments

@colin-young
Copy link

I've got things wired up with Autofac now, and I'm getting the Link in the header, but when I try to view the docs I'm getting: Hydra.Discovery.SupportedProperties.ApiDocumentationException: Property System.String String is not included in the context

I've got a single class registered with the SupportedClass attribute, and the first property throws that exception. When I step into the code, it appears that the DefaultPropertyIdProvider is getting a ContextProvider of type NullContextProvider which appears to be hard-coded to return null.

[SupportedClass("http://example.api/o#TestItem")]
public class TestItem
{
    public TestItem(string s)
    {
        String = s;
    }

    public string String { get; private set; }
    public string String2 { get; set; }
}

Clearly I'm missing a vital step or two in configuring my components.

@tpluscode
Copy link
Contributor

Yes, indeed, my fault it's missing from the readme.

Each model needs a JSON-LD @context. It's part of JsonLd.Entities and can come from the model's Context property or an IContextProvider. Here's a relevant, albeit incomplete, documentation page which describes how to define a context directly in model.

IContextProvider is self-explanatory. And you'll have to register it with the container.

Finally, you don't have to create the context from scratch. There are some helper classes.

@colin-young
Copy link
Author

Ha ha. Yeah. That explains it. I'll give that a try tomorrow when I'm back at my work computer.

@colin-young
Copy link
Author

Working now. Thanks! I've taken a to-do note to create a PR for updating the docs. I appreciate all your help and I'm more than happy to contribute some fixes.

Just for fun I slapped the Nancy.Swagger package in there, so now I can have Swagger or Hydra docs.

Looking into the Example/TestNancyApp code, it appears as though I will need to detail all my operations in SupportedOperations<T> classes? I wonder if it would be possible to go down the route of Nancy.Swagger.Annotations to allow a more declarative style of defining operations? Maybe even use the same attributes (possibly pulling them out into a new, more generic, shared project)? As much as I like the Hydra-style docs, there is a huge installed base of Swagger, and it's definitely got a lot of mind-share in the dev community, so it would be nice to have an easy transition path.

@tpluscode
Copy link
Contributor

Working now. Thanks! I've taken a to-do note to create a PR for updating the docs. I appreciate all your help and I'm more than happy to contribute some fixes.

Great. Any help will be much appreciated. Please note that I'm close to completing the #6 PR which introduces some new features and changes the library structure. I think maybe I'll make it happen over the weekend.

I wonder if it would be possible to go down the route of Nancy.Swagger.Annotations

Definitely a possibility although personally I'm not to keen on declarative way for operations. The important difference between Swagger et. al. and Hydra/hypermedia I usually emphasize is that hypermedia controls (both links and operations) are more dynamic in nature. With Nancy it's trivial to inject something into SupportedOperations<T> and decide whether to include a particular operation or not. For example to produce different ApiDocumentation depending on caller's permissions.

@tpluscode
Copy link
Contributor

A more important feature for me would be support for inline operations. Haven't figured out how to do it yet. I was considering a similar approach that Dan Barua's Nancy.Hal has that the API is kind external to the model itself. On the other hand Hydra models shouldn't be mixed with other layers so maybe it's not a problem

@colin-young
Copy link
Author

I hold off on a PR for documentation updates until you push #6 so I have a chance to review them for any further changes from the PR.

I haven't had much time to play with the Nancy.Swagger.Annotations, but I was hoping they would be responsive to the user permissions (but, I suspect not). It didn't occur to me to try injecting into SupportedOperations<T>. I'll have to look into that, and it seems like a good candidate for more example docs.

I still think the declarative approach has merit, it would just need to be able to adapt dynamically. I had sort of assumed that the documentation plugins would just use the route cache to figure out the available operations. Apparently I was wrong :) Certainly not the first time, and won't be the last. One of the things I'm trying to avoid is having to manually keep the documentation in sync with changes to controllers. It's one more task for a developer to forget.

@tpluscode
Copy link
Contributor

I'm trying to avoid is having to manually keep the documentation in sync with changes to controllers

Ah yes, that's what I'm attempting to address but from the other end. Instead of keeping docs in sync with controllers, I want to reverse that relation. Similar to ServiceStack where the route is associated with a Request model. Something like

[Identifier("/some/resource/{id}")]
public class MyModel
{
}

public class MyModule : ArgolisModule
{
   public MyModule()
   {
      Get<MyModel>(o => new MyModel(o.id));
      Post<MyModel>(o => this.Process(this.Bind<MyModel>());
   }
}

This way you only define the route once. There are also utilities for getting identifiers from these templates (must be RFC syntax, not Nancy syntax)

IUriTemplateExpander expander;
Uri id = expander.Expand<MyModel>(new { id = 10 }); // /some/resource/10

@colin-young
Copy link
Author

So... is ArgolisModule intended to replace NancyModule? As in, replacing Nancy? Or just deriving from it? Or am I completely missing the point?

Otherwise, I'm in agreement with the only define things once and I'm not fussy about which end it's done from. There are compelling arguments for doing it from the documentation end as you're suggesting.

@tpluscode
Copy link
Contributor

tpluscode commented Feb 24, 2017

It derives from NancyModule and introduces an additional set of Get/Put/etc methods as you see above and also adds routing with URI Templates (see here and here)

@colin-young
Copy link
Author

Nice! I'll check that out after you've finished the PR. I've got some Serilog sink work I've been neglecting, so that should keep me busy in the meantime.

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

No branches or pull requests

2 participants