I am trying to infer a schema from my ASP.NET API via OpenAPI in Radzen. It seems to work so far, but there is one problem.
In my code I am using a default value in the method siganture (see the bool "useSample"):
[ApiController]
[Route("[controller]")]
public class TestController : ControllerBase
{
private readonly ILogger<TestController> _logger;
public TestController(ILogger<TestController> logger)
{
_logger = logger;
}
[HttpGet("Test/{value}")]
[ProducesResponseType(typeof(Model), StatusCodes.Status200OK)]
public IActionResult GetTest(string value, bool useSample = true)
{
var model = new Model
{
Name = "Test Name",
Age = 30
};
if (useSample)
model.Name = "Another Sample Name";
return Ok(model);
}
public class Model
{
public string? Name { get; set; }
public int Age { get; set; }
}
}
The generated output is invalid C# code (the word "True" is written with a capital T but it must be lower case!):
public partial class MyServiceService
{
...
public async Task<Test2.Models.MyService.Model> GetTestTestValue(string value, bool useSample = True)
{
...
}
}
However, I found another, related bug which you will come accross if you have methods with default parameters. In C#, default parameters always have to be at the end of the method signature! E.g.:
public void Test(int number, string atext = "some text")
Now, when the OpenAPI json file is created for such a method, the order to the parameters may change (I assume these get ordered alphabetically!).
When you generate the C# stub from the JSON file back then, you stick to the order in the JSON file which can result in the following ouput:
public void Test(string atext = "some text", int number)
This is invalid C# code. So it would be required when you generate the C# stubs that you split the parameters into a list with default and one without default parameters and output the ones without first.
One more thing, since I'm taking a closer look at this feature: You offer the option of providing an API key.
This key is stored in the appsettings.json file, and then hard-copied into the generated C# file. However, this is not a good approach since credentials should never be hardcoded.
In my setup, I work with multiple appsettings.json files for different environments (dev, staging, and production). Having the API key hard-coded makes it impossible for me to switch environments.
This is handled better for SQL data sources since you grab the credentials from the connection string in the appsettings.json file at runtime via configuration.
Ideally, you could use this approach for the OpenAPI data source as well.
Thanks a lot!
P.S.: The same applies also for the service address/URL, which is also hard coded in program.cs at the moment - it would generally be a better approach to have the service URL and the API key as settings in the appconfig.json and use the Configutaration system to get the values in the actual code.
Of course the generated code can easily be modified afterwards but in case I do a new infer of the data source beause e.g. I updated my API with new methods, all the changes will get lost...
That is correct. However, the current approach is not very flexible at all.
It would help if re-infering the API would not overwrite the authentication method or if these kind of methods as well as the service API could be declared in a way that one could overwrite it with custom code in a partial class.
builder.Services.AddHttpClient("MyAPI", client => client.BaseAddress = new Uri("https://localhost:7039"));
Both contain information form the actual configuration that needs to be replaced and will be overwritten on every infer.
A partial class or implementation does not help in this case.
But I have a better idea since you mentioned that using the settings from the Configutration is not an option due to compatibilty to Wasm:
Why don't you add a checkbox/bool option to the infer dialog (only available on re-infer) which prevents the code in program.cs and the AuthorizeRequest method from being overwritten, so somthing like "Only infer API and not update access information"?
That would help since I can implement my own, custom code after the first infer and when doing a re-infer, the code remains and does not get overwritten... what do you think?
That's probably a solution but definitely not trivial to implement. It would still work only for non-wasm cases which is a bit limiting. If Microsoft provides some equivalent to appsettings.json and Configuration for WASM we would definitely use it as we do for everything else.
Well, generally you are right but at the moment, this is the only approach I see and it also would work with Wasm since if you tick the checkbox, the original code does not get overwritten and it would still work. Actually the only difference compared to the current state is that some parts of the generated code do not get updated, if the option is checked. By default it is not checked and everything will behave like it does right now. So I do not see a limitation here...