dotnet / aspnet-api-versioning

Provides a set of libraries which add service API versioning to ASP.NET Web API, OData with ASP.NET Web API, and ASP.NET Core.
MIT License
3.05k stars 703 forks source link

Method not found: 'Asp.Versioning.ApiVersion Asp.Versioning.IApiVersionParser.Parse(System.String)' #1005

Closed MHKarami97 closed 1 year ago

MHKarami97 commented 1 year ago

Is there an existing issue for this?

Describe the bug

I use this code to add version on .net freamwork 4.6.2:

Asp.Versioning.WebApi : 7.0.0 Asp.Versioning.WebApi.ApiExplorer : 7.0.0

config:

config.MapHttpAttributeRoutes();
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/v{apiVersion}/{controller}/{action}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
            config.AddApiVersioning(options =>
                {
                    options.ReportApiVersions = true;
                    options.AssumeDefaultVersionWhenUnspecified = true;
                    options.Conventions.Add(new VersionByNamespaceConvention());
                    options.DefaultApiVersion = new ApiVersion(1, 0);
                    options.ApiVersionReader = ApiVersionReader.Combine(
                        new UrlSegmentApiVersionReader(),
                        new HeaderApiVersionReader("x-api-version"),
                        new MediaTypeApiVersionReader("x-api-version"));
                }
            );
SwaggerConfig.Register(config);

controller

[HandleError]
    [ApiVersion("1")]
    [System.Web.Http.AllowAnonymous]
    [Route("api/v{version:apiVersion}/[controller]/[action]")]
    public class BaseController : ApiController
    {
}
[ApiVersion("1")]
public class CustomerController : BaseController
{
}

but when call api method like this, I get error:

http://localhost:63593/api/v1/Customer/GetErrors?userCode=1

<Error ml-update="aware" ml-stage="preload" ml-view="top">
<Message>An error has occurred.</Message>
<ExceptionMessage>Method not found: 'Asp.Versioning.ApiVersion Asp.Versioning.IApiVersionParser.Parse(System.String)'.</ExceptionMessage>
<ExceptionType>System.MissingMethodException</ExceptionType>
<StackTrace> at Asp.Versioning.ApiVersionRequestProperties.get_RequestedApiVersion() at Asp.Versioning.Dispatcher.ControllerSelectionContext.get_RequestedVersion() at Asp.Versioning.Dispatcher.DirectRouteControllerSelector.SelectController(ControllerSelectionContext context) at Asp.Versioning.Dispatcher.ApiVersionControllerSelector.SelectController(HttpRequestMessage request) at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__15.MoveNext()</StackTrace>
</Error>

Expected Behavior

No response

Steps To Reproduce

No response

Exceptions (if any)

No response

.NET Version

No response

Anything else?

No response

commonsensesoftware commented 1 year ago

This all looks correct. Something is amiss at runtime. It's like the assembly isn't present or something. Do you have project that reproduces this behavior? .NET 4.6.2 is supported and I don't see any reason why this would not work.

commonsensesoftware commented 1 year ago

Last call. Did you ever find the cause of this? Did you create a repro? This looks an assembly was not copied to the output directory or the output needed to be cleaned.

commonsensesoftware commented 1 year ago

No more information was provided so it seems you solved the problem or abandoned the issue. MissingMethodException implies that an assembly was not copied or deployed with your application or somehow the wrong reference is being used. If you're ever able to provide more context and it wasn't solved, I can help dig into it further.

markjerz commented 1 year ago

I hit this as well with an existing project. For anyone else who has the problem I checked my build warnings and noticed one about bindingredirects that I needed to add. Specifically, in my case:

<dependentAssembly>
  <assemblyIdentity name="Microsoft.Owin.Host.SystemWeb" culture="neutral" publicKeyToken="31bf3856ad364e35" />
  <bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>

I also had a warning around needing to install the Microsoft.Bcl.Async library as well.

Did both of those and it seems to be back working.

commonsensesoftware commented 1 year ago

@markjerz Thanks for the follow up information. I had a suspicion it was something like that, but I had no other information and I couldn't repro the conditions. I'm sure this will be useful to anyone else that hits this issue.

johnGeorge4 commented 6 months ago

I've run into this issue as well - I've unloaded my projects and then reloaded with dependencies. I saw some warnings about conflicts requiring bindingredircts so I took care of those. Since VS doesn't like to clean solutions I closed the project and deleted the /bin and /obj folders from my project folders, then opened the project again and built the solution.

When I run the program I can access my non-api controller methods, but when I try to call my API methods using postman I get the following error:

"Message": "An error has occurred.",
"ExceptionMessage": "Method not found: 'Asp.Versioning.ApiVersion Asp.Versioning.IApiVersionParser.Parse(System.String)'.",
"ExceptionType": "System.MissingMethodException",
"StackTrace": "   at Asp.Versioning.ApiVersionRequestProperties.get_RequestedApiVersion()\r\n   at Asp.Versioning.Dispatcher.ControllerSelectionContext.get_RequestedVersion()\r\n   at Asp.Versioning.Dispatcher.DirectRouteControllerSelector.SelectController(ControllerSelectionContext context)\r\n   at Asp.Versioning.Dispatcher.ApiVersionControllerSelector.SelectController(HttpRequestMessage request)\r\n   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__15.MoveNext()"
commonsensesoftware commented 6 months ago

I think I finally understand why this might be happening. I've provided a detailed explanation in:

https://github.com/dotnet/aspnet-api-versioning/discussions/1079#discussioncomment-9216115

The short, short answer is that if you are targeting .NET Framework greater than 4.5, but less than 4.7.2 and you directly reference Asp.Versioning.Abstractions, NuGet is going to resolve an incompatible combination. The solutions are:

  1. Target .NET 4.7.2 or above
  2. Do not directly reference Asp.Versioning.Abstractions
    • NuGet will resolve it as a transitive dependency with .NET Standard 1.0

If this works for you, please share so that others can benefit from it.

johnGeorge4 commented 6 months ago

I found a similar solution last night that follows your first suggestion - I updated the project's framework to .NET 4.8.

I'm in the process of updating a few packages in the project that had an issue with updating the framework (got to love NetStandard throwing errors at runtime) and planned on posting a follow-up once I got the Asp.Versioning package integrated and working completely.

commonsensesoftware commented 6 months ago

@johnGeorge4 good to know that seems to be putting on you on the right path. This is less of a .NET Standard issue itself and more of a NuGet resolution problem. .NET Standard is just a set of API contracts; it isn't a runtime. The reason MissingMethodException happens is that .NET 4.5 is being resolved as a direct dependency, but the transitive dependency to Asp.Versioning.Abstractions is being resolved to a higher version. The method signatures between .NET 4.5 and .NET Standard 2.0 are different. The .NET 4.5 implementation is expecting .NET Standard 1.0. This results in an incompatible mismatch.

johnGeorge4 commented 6 months ago

Had to do some digging into my web.config, but eventually I found where my framework was still being set to the .NET 4.6.1 so I updated it to 4.8.0 and then included the netstandard assembly that I found here: https://stackoverflow.com/a/51743098

This let my project finally run successfully. I then used this response (https://github.com/dotnet/aspnet-api-versioning/discussions/1082#discussioncomment-9183553) to help get my routing on the controller level fixed so I could make a call from Postman to one of my test APIs. Thanks for all the help! I really appreciate it!