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
167 stars 38 forks source link

Error on generating Api (Model Binding) #48

Closed jfantunes closed 6 years ago

jfantunes commented 6 years ago

Hi Zijan, first of all good work. I really apreciate your library. Altough i'm having some troubles putting it working as expected. I'm getting this error and don't know how to workaround.

System.ArgumentException: 'How can it be with this ParameterBindingAttribute: ModelBinding'

My config data being passed to the controller is this one:

{
  "ApiSelections": {
    "ExcludedControllerNames": [],

    "DataModelAssemblyNames": [
      "MIMS.Dtos"
    ],
    "CherryPickingMethods": 1
  },

  "ClientApiOutputs": {
    "ClientLibraryProjectFolderName": "MIMS.WebApi.Client",
    "GenerateBothAsyncAndSync": true,

    "CamelCase": true,
    "TypeScriptJQFolder": "",
    "TypeScriptNG2Folder": "..\\MIMS.WebApi.Client\\AngularApi"
  }
}

Thanks!

zijianhuang commented 6 years ago

You have better to tell if your Web API is with ASP.NET or .NET Core, but I guess it is with .NET Core. Anyway, apparently one of the Web API functions is not declared properly, or WebApiClientGen hasn't yet supported such declaration.

In WebApiClientGenCore, here's where the exception is thrown:

    public static class MetaTransform
    {
        static ParameterBinder GetParameterBinder(BindingSource bindingSource)
        {
            if (bindingSource == null)
                return ParameterBinder.None;

            if (BindingSource.Path.CanAcceptDataFrom(bindingSource))
                return ParameterBinder.FromUri;

            if (BindingSource.Query.CanAcceptDataFrom(bindingSource))
                return ParameterBinder.FromUri;

            if (BindingSource.Body.CanAcceptDataFrom(bindingSource))
                return ParameterBinder.FromBody;

            if (BindingSource.ModelBinding.CanAcceptDataFrom(bindingSource))
                return ParameterBinder.FromUri;

            throw new ArgumentException($"How can it be with this ParameterBindingAttribute: {bindingSource.DisplayName}", "bindingSource");
        }

Apparently the offending Web API function is with none of the 4 binding sources outlined above. Please check your Web API codes.

jfantunes commented 6 years ago

Thanks that did the trick. Just one more question i have. I have several dto's that i want to convert but they use a generic approach public class MimsResult { ///

/// The result of the search /// public T Result { get; set; }

    /// <summary>
    /// At what time the results were generated
    /// </summary>
    public DateTime GeneratedAt { get; set; } = DateTime.Now;

    /// <summary>
    /// If the search was successful
    /// </summary>
    public bool Success { get; set; } = true;

    /// <summary>
    /// The http log message
    /// </summary>
    public string Message { get; set; }
}

For what im observing he doesnt like it. Is there a way to turn around this?

zijianhuang commented 6 years ago

Generic class is a bit similar to template of C++, and is not really a concrete class, and there's no way for the client program to interpret. MimsResult may be handled though. So your question is basically a C# question, off-topic.

Before I close this issue, would you mind showing your offending API function so I may be considering better handling as I had documented in #49.

jfantunes commented 6 years ago

@zijianhuang i didn't understood your point, because i was using this class in the client code, i had a gulp script that converted only the models and it converted with generics. Now using this library in order to generate my dtos i have to put it as a Json atributte and getting after the classes defined with

public class MimsResult `1

And if i choose the cherrypicking for 0 and 8 which i think are the aproaches that satisfied me most on the cases i have i'm always getting this error 'System.ArgumentNullException: 'Value cannot be null.' on this line CodeGen.GenerateClientAPIs(webRootPath, settings, apiDescriptions);. For me it's a question relatively to this program since i don't know how he can hadle the generic classes interpretation, since with other programs i used and i didn't have problems with it. But i must state that the other program used was only for dto generation.

Regarding to the offend function i just converted this:

[HttpGet]
        [ValidateAttributes]
        public IActionResult GetAll(Paging properties)
        {
            var buffers = _bufferService.GetBuffersPaged(properties);
            var successfull = buffers != null;
            var total = buffers?.Total ?? 0;

            var response = new MimsPagedResult<BufferDto>
            {
                Result = buffers?.Result,
                Total = total,
                Success = successfull
            };

            return new ObjectResult(response);
        }

Into this

[HttpGet]
        [ValidateAttributes]
        public IActionResult GetAll([FromRoute]Paging properties)
        {
            var buffers = _bufferService.GetBuffersPaged(properties);
            var successfull = buffers != null;
            var total = buffers?.Total ?? 0;

            var response = new MimsPagedResult<BufferDto>
            {
                Result = buffers?.Result,
                Total = total,
                Success = successfull
            };

            return new ObjectResult(response);
        }

Thanks

zijianhuang commented 6 years ago

@jfantunes, somehow the Github editor had eaten some characters I had written above. I would write again.

Generic class is a bit similar to template of C++, and is not really a concrete class, and there's no way for the client program to interpret. MimsResult<string> or MimsResult<BufferDto> may be handled though, because .NET runtime create such classes at runtime. .

Thanks for providing the offending API function, so I may be explicitly giving more specific error message about this in next release.

.NET Core Web API has slightly different convention in using attributes, so more specific error message could help app developers to find the offender.

I am closing this issue. If you want to resolve MimsResult<T>, please open a new issue.