zijianhuang / webapiclientgen

Strongly Typed Client API Generators generate strongly typed client APIs in C# .NET and in TypeScript for jQuery and Angular 2+ from ASP.NET Web API and .NET Core Web API
MIT License
168 stars 38 forks source link

Generate strong typed class / interface for dynamic object #103

Closed Gambero81 closed 3 years ago

Gambero81 commented 4 years ago

As i can understand currently dynamic objects are managed returning a JObject (https://github.com/zijianhuang/webapiclientgen/wiki/Dynamic-Object)

It would be great to generate a strong typed class who represent the object.

zijianhuang commented 4 years ago

In what scenarios you would use dynamic object in Web API?

If always returning the same type of object, why won't you strongly type the return type in the first place?

if returning different types of object, it is expected the codegen to parse all return paths to find out all possible return types, which is a CA job. And C# does not support prototyping of multiple return types, though TypeScript supports.

Are there other scenarios you would use dynamic object?

How about the suggestion of using Tuple as an alternative giving you certain level of "dynamic"?

Gambero81 commented 4 years ago

Hi @zijianhuang , In my company we use dynamic return type for each api return to speed up the development, avoiding to create for each api method a class who define the return type. An api return ALWAYS the same type of object.

Now we use asp.net mvc with angular front-end and to generate the client api wrapper i use TypeWriter. To generate che strong typed class of dynamic api return i have implemented a cli application integrated in post build events who analyze the controller code and generate a class with strong typed classes related to the anonymous return type of controller methods.

Now i have to develop a Blazor wasm application hosted in asp.net core and i would like to use your project to generate api client wrapper because TypeWriter seem to be a dead project with no update.

The flexibility of TypeWriter allow me to manage the anonymous types generating the strong typed classes externally, but using WebApiClientGen i can't do it.

Here an extract of code using roslyn library i use to generate the strong type from anonymous type: `

         var typeInfo = semanticModel.GetTypeInfo(identifierNameSyntax);
         var type = typeInfo.Type;

        isAnonymousType = type.IsAnonymousType;
        if (!isAnonymousType)
        {
            returnType = type.ToString();
            return true;
        }

        if (type.Kind != SymbolKind.NamedType)
            return false;

        //Properties of anonymous type
        anonymousTypeProperties = new Dictionary<string, string>();
        var members = type.GetMembers();
        foreach (var member in members)
        {
            if (member.Kind != SymbolKind.Property)
                continue;

            var memberProperty = (IPropertySymbol)member;
            var propertyType = memberProperty.Type.ToString();
            var propertyName = memberProperty.Name;

            anonymousTypeProperties.Add(propertyName, propertyType);
        }`

I think who implement this feature will be a great improvement in the WebApiClientGen project!

Thanks

zijianhuang commented 4 years ago

Have you read https://github.com/zijianhuang/webapiclientgen/wiki/Compare-with-TypeLITE-and-TypeWriter?

Any feature that TypeWriter has while Poco2TS.exe does not have?

Noticeably TypeWriter generates classes not interfaces.

Please note, WebApiClientGen is optimized for RPC not REST, contracting with strong typing and not dynamic.

Regarding Blazor wasm, have you read https://github.com/zijianhuang/webapiclientgen/issues/94 ?

zijianhuang commented 4 years ago

@"manage the anonymous types generating the strong typed classes externally"

I am not quite sure what you mean. Can you provide some examples to explain?

Gambero81 commented 4 years ago

@zijianhuang

@"manage the anonymous types generating the strong typed classes externally"

I am not quite sure what you mean. Can you provide some examples to explain?

In our Blazor application we have controllers for web application and controllers for api integrations: in controllers for web application we manage anonymous return type to speed up the development time avoid to generate for each method the corresponding return type class.

In build events i call an application who analyze the controllers source code, check for anonymous return type, generating the corresponding strong typed classes, and generating the strong typed client httpService.

for example:

public class MyController: ControllerBase
{
   [HttpGet]
   public async Task<IActionResult> MyMethod(string vat)
   {
      var result = new {
         Result = true,
         ErrorMessage = ""
      };

      return Ok(result);
   }
}

analyzing this controller my application generate 2 files: MyController.auto.cs:

public class MyMethodResult
{
   public bool Result {get;set;}
   public string ErrorMessage {get;set;}
}

MyController.HttpClient.auto.cs

public class MyControllerHttpService: HttpService
{
   public Task<MyControllerResult> MyMethod(string vat)
   {
      var parameters = new Dictionary<string, object>();
         parameters.Add(nameof(vat), vat);

         var result = await GetAsync<MyMethodResult>("web/MyMethod", parameters);

         return result;
   }
}
zijianhuang commented 3 years ago

this is out of the scope of this project.

Related to #94 and #92