-
Notifications
You must be signed in to change notification settings - Fork 6k
Nancyfx codegen (C#) #3178
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
Nancyfx codegen (C#) #3178
Conversation
Fixed package name to case-sensitive in GoClientOptionsTest, GoModelTest, LumenServerOptionsTest and SpringBootServerOptionsTest
|
To your point about sample code, that's not a common approach in many open source projects (including Swagger Codegen). Samples are provided as part of the github repository, and generated by bash scripts. They're not only useful for users to see the generated output, but are also used to programmatically check the validity of the generated samples. For .NET generated sources intended to only run on Windows, we wouldn't programmatically execute them in non-Windows environments but maintainers do run bash scripts and compile the generated code on non-Windows environments to quickly verify changes. The samples aren't included in compiled binary output. I don't disagree with you, though. I think a separate location for examples could be a cleaner approach for many projects, and certainly wouldn't clutter source with auto-generated code. The reason to include a build.sh and build.bat file is because not every developer is using Visual Studio with integrated NuGet. Some developers (like myself) use Xamarin on OS X, in which only the beta version 6.0 currently automates NuGet package management. XBuild and MSBuild can build .sln and .csproj directly, but they have no knowledge of NuGet. In addition, many developers on Windows are now switching to Visual Studio Code as a lightweight and less memory intensive alternative to Visual Studio. I haven't checked version 1.2 of Visual Studio Code, but I believe version 1.1 hasn't yet integrated NuGet. Build scripts would help automate this NuGet restoration process. For example, the C# Client batch file downloads NuGet, references the dependencies, and compile sources. I agree with your last point about moving any bootstrapper helper to a future addition. Once this PR is merged, I think we should create an issue to track that. I think the use case you presented would be helpful in a README.md output with the generated source. |
|
@mstefaniuk it's definitely a good start 👍 I'll merge tomorrow (Tuesday) and also share my views on some of your questions/feedback above. |
|
@mstefaniuk I also agree, it's a great start. When I created the aspnet5 generator, I was originally going to contribute a nancyfx generator against vNext but decided against it because things were in such flux that I could generate a server using the aspnet yeoman generator one day and it would work then generate the same thing three days later and it wouldn't! Somewhat unrelated to the PR, a friend of mine wrote a sort of dynamic REST api abstraction on top of NancyFX. gwely/Napi if you're interested in checking it out. |
|
@jimschubert thanks for reviewing the change. @mstefaniuk thanks for the PR. About enum naming, I agree yours is better. The one you see in C# is done by the one who contributed the enum support in C#. I'll give that contributor a heads-up before switching to yours. |
|
@wing328 no problem. I don't think we can easily switch from the Enum suffix to this implementation, although I agree @mstefaniuk has a better implementation. The reason is that changing |
|
One fallback I can think of is to use vendor extension (e.g. x-csharp-enum-prefix, x-csharp-enum-suffix) and developers can then customize the enum prefix/suffix per property/parameter/class |
|
That's a great idea. |
|
|
||
| Delete["/user/{username}"] = parameters => | ||
| { | ||
| var username = Parameters.ValueOf<string>(parameters, Context.Request, "username", ParameterType.Path); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NancyFX core contributor here - what is Parameters.ValueOf doing. If trying to get the username from the querstring then we have different syntax to do that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jchannon thanks for reviewing the code (and sorry for late reply as I missed your question)
I think it's trying to obtain username from the path. e.g. if path is /user/wing328, then username will store "wing328". In other words, it's not a query string.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could do parameters.username to get that value. I assume your Parameters.ValueOf is some wrapper around it all. Not sure why but will assume you have a good reason
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jchannon I'm not the author so I don't know the exact reason.
My guess is that username can be of different type (defined in swagger spec), e.g. date, double, string, etc and that's why it needs to call Parameters.ValueOf<datatype> to cast the value into the type defined in the spec.
|
A basic |
|
I really struggle to understand how this is supposed to work, I know I need to implement either the interface or the abstraction. But how do I handle errors and return my error message using this generated code? |
|
@simo9000 please submit a PR to update Nancyfx to the latest version if you've not done so. |
|
@razzeee I agree with you that we should add a README for Nancyfx (just like other auto-generated code)
I think this is more of a question for Nancyfx itself as swagger codegen simply generates the code and you can then perform the error handling with respect to Nancyfx best practices. |
|
@wing328 |
|
@razzeee This generator doesn't currently support non-200 response types. This PR is the initial implementation to get the stubbed server generated code. For example, the petstore.yaml used to generate the sample has the following PUT operation on put:
tags:
- pet
summary: Update an existing pet
description: ''
operationId: updatePet
consumes:
- application/json
- application/xml
produces:
- application/xml
- application/json
parameters:
- in: body
name: body
description: Pet object that needs to be added to the store
required: true
schema:
$ref: '#/definitions/Pet'
responses:
'400':
description: Invalid ID supplied
'404':
description: Pet not found
'405':
description: Validation exception
security:
- petstore_auth:
- 'write:pets'
- 'read:pets'The generated code is: It looks like this is handling:
Things missing from the swagger definition:
We could add summary, description, and operationId to the generated code. Custom responses and security are implementation details which may be difficult. Using the example above:
Because these things are all contextual and based on your domain/implementation, it would be difficult to "get it right" from a generator's perspective. There are things that could be done by following community standards or best practices. For instance, a common set of exceptions could be generated to be thrown by services, and a global exception handling mechanism could respond with those 4xx and 5xx exceptions. A user of the swagger generation tool can add rules to I hope that answers some of your questions or concerns. |
|
@jimschubert I'm not whining that the generator doesn't generate error responses. I'm just wondering how I need to implement them in a nice way using this. |
|
@razzeee I definitely didn't think you were whining ;). Do you have a project on Github that follows your pattern? I'm wondering if there's a way to modify the existing generator to account for your code goals. I have pretty limited experience with NancyFX, so I'm not familiar with what's considered a best practice. Also, it's possible for you to edit the templates to meet your needs, then specify the custom templates when you run the CLI. Is that something you'd be willing to try? This way, you should be able to get the Response output as you posted and have the files structured in a way you're more familiar with. |
|
@jimschubert Then the content negotiation of nancyfx, should handle whatever you throw it's way.
I'll have a look if I can modify the generator in a way to do that, and create a petstore example. |
|
Here is a draft https://github.com/Razzeee/swagger-codegen/tree/nancyfx-dynamic |
|
@razzeee In NancyFX you can handle exceptions and return error JSON messages. You can add ((context, exception) =>
{
var response = context.Response ?? new Response();
var result = mapper.Handle(context, exception);
response.Write(result);
if (!string.IsNullOrEmpty(response.ContentType))
{
response.Headers.Put(HttpHeaders.ContentType, response.ContentType);
}
return response;
})In above code namespace Commons.Nancy.Error.Handlers
{
public class PreconditionFailedHandler: ExceptionHandler
{
public ErrorResponse Handle(NancyContext context, Exception e)
{
var exception = (PreconditionFailed) e;
var body = new ErrorMessage(exception.Code, exception.Message);
return new ErrorResponse(HttpStatusCode.PreconditionFailed, body);
}
}
}I'm not sure what can |
|
@msolujic Edit: Ah, you said bootstraper, so it might be hard to get it into codegen :/ |
Actually it is not hard at all. Nancy is designed to allow easy subclassing of the bootstrapper. The codegen for nancyfx doesn't currently have a bootstrapper.mustache but it would be very easy to add one in a PR. I agree with @msolujic that exception handling is a preferred means to dynamic return values. I would suggest making a |
For API clients generated by Swagger Codegen, there's usually an |
|
Well I'm toying with this right now protected override void RequestStartup(TinyIoCContainer container, IPipelines pipelines, NancyContext context)
{
pipelines.OnError.AddItemToEndOfPipeline((ctx, ex) =>
{
DefaultJsonSerializer serializer = new DefaultJsonSerializer();
Response error = new JsonResponse(ex.Message, serializer);
if (ex is ArgumentException)
{
error.StatusCode = HttpStatusCode.PreconditionFailed;
}
else
{
error.StatusCode = HttpStatusCode.InternalServerError;
}
return error;
});
base.RequestStartup(container, pipelines, context);
}But it's not as elegant as I would like it. |
|
@razzeee We considered to provide error handling within codegen but it would force users to use particular implementation of that. Those services can be part of bigger solution so it would be wrong decision. I'm not sure what mean to abuse exception but you can simply create your own exceptions as we created |
|
That might work nicely. Thanks! |
|
@razzeee @mstefaniuk what might be a good compromise is to create a bootstrap.mustache and an apiexception.mustache to forward exceptions as JSON with the response code. Then to ensure backward capability, create a generator option which, if true, will conditionally add the |
|
Building on @razzeee 's points, I'm not understanding how to get the nancy swagger auto generated code running and some documentation would save everyone some frustration. It seems @razzeee was finally able to get it running, but I'm still stuck. The wiki doesn't have any useful information about using the auto generated code. I will happily put in a pull-request with an update to the docs if I can get the instructions straight. Here's what I have so far (of course I haven't gotten it working yet so any help would be greatly appreciated):
For Nancy-2.0.0 Then accessing
|
|
@mikob Generated code contains Nancy module so it is autowired by IoC bootstraper. Please look at UserModule from PetStore sample. There is I'm not sure how it is related but generated code was focused on Nancy 1.4.1 and you mention about version 2.0.0. |

Here you have codegen for .NET NancyFX framework. It generates code for library that should be shared as compiled artifact (NuGet). So there is no tests but Nancy REST module, service interface and simplified abstract implementation. It is heavily tested within private projects.