【问题标题】:CS7069: Reference to type 'Route' claims it is defined in System.Web but it could not be foundCS7069:对类型“Route”的引用声称它在 System.Web 中定义,但找不到
【发布时间】:2019-12-28 18:04:44
【问题描述】:

我正在尝试使用 this tutorial 将 OAuth 2.0 添加到我的 .NET Core 3.0 Web Api。以下是WebApiConfig类的内容。

        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services  
            // Configure Web API to use only bearer token authentication.  
            config.SuppressDefaultHostAuthentication();
            config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));

            // Web API routes  
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute( // HERE IS THE ERROR
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

            // WebAPI when dealing with JSON & JavaScript!  
            // Setup json serialization to serialize classes to camel (std. Json format)  
            var formatter = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
            formatter.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver();

            // Adding JSON type web api formatting.  
            config.Formatters.Clear();
            config.Formatters.Add(formatter);
        }

我猜它与依赖关系有关,所以这里是 csproj:

  <ItemGroup>
    <PackageReference Include="EntityFramework" Version="6.4.0" />
    <PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.7" />
    <PackageReference Include="Microsoft.AspNet.WebApi.Core" Version="5.2.7" />
    <PackageReference Include="Microsoft.AspNet.WebApi.Owin" Version="5.2.7" />
    <PackageReference Include="Microsoft.AspNet.WebApi.WebHost" Version="5.2.7" />
    <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.1.0" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.0.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.0.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.0.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.0">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.0.0" />
    <PackageReference Include="Microsoft.Owin.Cors" Version="4.1.0" />
    <PackageReference Include="Microsoft.Owin.Security.OAuth" Version="4.1.0" />
    <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.0.0" />
    <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
  </ItemGroup>

我看到了一个类似的问题,其中一个答案建议使用 app.UseMvc 来映射路线,但他使用的是不同的 .NET 版本 (2.0)。我也尝试使用 app.UseMvc 但它什么也没做,因为我使用 EndpointRouting。

    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddIdentity<AppUser, AppRole>(options =>
             {
                 options.User.RequireUniqueEmail = true;
             }).AddEntityFrameworkStores<AppDbContext>();


            services.AddControllers();

            //+adding database and service/repository
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

            app.UseAuthentication();



            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });

        }
    }

所以我不太确定该怎么做。我尝试关闭 Visual Studio 并删除项目中的每个 obj、bin 和 vs 文件夹(听起来很奇怪,有些人认为它可以工作)但没有成功。

有什么建议吗?

【问题讨论】:

标签: c# asp.net-web-api oauth asp.net-core-3.0


【解决方案1】:

这是一个我也遇到过的棘手问题,但是当我搜索此错误消息的解决方案时,似乎没有人有一个优雅的解决方案......所以我自己找到了一个。

这里有几个问题:

  1. 如报错信息指出,方法MapHttpRoute已定义但找不到

    • 原因很简单:定义 HttpRouteCollectionExtensions 方法的文件不包含方法的实际主体!
    • 这个文件是在我们通过 NugGet 添加 Microsoft.AspNet.WebApi 包时安装的,它通过包含“using System.Web.Http;”来引用在文件的顶部
    • 因此对我有用的解决方案就是获取这些扩展的源代码并将它们直接包含在我的项目中
    • 您可以在此处获取此源代码:

https://github.com/mono/aspnetwebstack/blob/master/src/System.Web.Http/HttpRouteCollectionExtensions.cs

  • 顺便说一下,在 GitHub 上,您还可以找到定义类似但未找到的其他方法的源代码(即它们似乎是由 Microsoft 提供的)

所以,这解决了实现 MapHttpRoute 方法的问题……但这并不一定意味着您的 restful 服务调用会起作用!

那是因为这里实现的 HttpDelete 服务有调用参数,必须通过 [Route] 和 [HttpDelete] 属性来定义......这导致我们进入第 2 步。

  1. 我们需要通过[Route]和[HttpDelete]属性显式声明调用参数

    • 这其实很简单,但很重要
    • 它将确保客户端在尝试访问 RESTful 服务时转到正确的位置
    • 就我而言,我有两个用于删除服务的调用参数,它们都是字符串
    • 因此我调用 config.Routes.MapHttpRoute(name, routeTemplate, defaults) 中的路由模板如下所示:

    routeTemplate = "api/{controller}/{userID}/{userName}";

    • 然后在 C# 控制器(即被调用的服务所在的文件)中,我修改了属性和服务方法,如下所示:

    [Route("[控制器]/{userID}/{userName}")]

    [HttpDelete("{userID}/{userName}")]

    public bool Delete(string userID, string userName) => this.DeleteUser(userID, userName);

    • 接下来我定义实际使用参数的方法:

    [路线(“[控制器]”)]

    public bool DeleteUser(string userIDParam, string userNameParam)

    {

    int?用户 ID = 0; 字符串用户名 = "";

    if (userIDParam != null) userID = Int16.Parse(userIDParam);

    如果(用户名参数!= null) 用户名 = 用户名参数;

    return DeleteSpecifiedUser(userID, userName);

    }

    • 在DeleteSpecifiedUser(userID, userName)方法中,这里没有展示,我在数据库中进行了实际的删除操作
    • 虽然在我的例子中我使用 ADO.Net,但它可以通过实体框架完成(但这超出了本次讨论的范围)
    • 当然,我可以将 userID 作为整数发送,但本示例旨在说明如何使用两个调用参数进行操作
    • 由于上面的原始问题只有一个调用参数(即 int id),那么这种情况就更简单了

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-23
    • 2018-09-12
    • 1970-01-01
    • 2019-02-21
    • 1970-01-01
    • 2021-11-29
    • 2018-04-11
    • 1970-01-01
    相关资源
    最近更新 更多