CS7069:对“路线”类型的引用声称它在System.Web中定义,但找不到

时间:2019-12-28 18:04:44

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

我正在尝试使用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文件夹(听起来有些奇怪,有人建议这样做),但没有成功。

有什么建议吗?

1 个答案:

答案 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方法的问题...但这并不一定意味着您可以轻松进行服务调用!

这是因为此处要实现的HttpDelete服务具有调用参数,必须通过[Route]和[HttpDelete]属性定义这些参数,这将导致我们进入步骤2。

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

    • 这实际上很简单,但这是必不可少的
    • 它将确保客户端尝试访问静态服务时到达正确的位置
    • 在我的情况下,我有两个用于删除服务的调用参数,它们都是字符串
    • 因此,在我对config.Routes.MapHttpRoute(name,routeTemplate,defaults)的调用中,路由模板如下所示:

    routeTemplate =“ api / {controller} / {userID} / {userName}”;

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

    [Route(“ [controller] / {userID} / {userName}”)]

    [HttpDelete(“ {userID} / {userName}”)]

    公共布尔Delete(字符串userID,字符串userName)=> this.DeleteUser(userID,userName);

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

    [Route(“ [controller]”)]

    公共布尔DeleteUser(字符串userIDParam,字符串userNameParam)

    {

    int? userID = 0; 字符串userName =“”;

    如果(userIDParam!= null) userID = Int16.Parse(userIDParam);

    如果(userNameParam!= null) userName = userNameParam;

    返回DeleteSpecifiedUser(userID,userName);

    }

    • 在此处未显示的方法DeleteSpecifiedUser(userID,userName)中,我在数据库中执行了实际的删除操作
    • 尽管在我的情况下,我使用ADO.Net,但可以通过实体框架来完成(但这超出了本讨论的范围)
    • 当然,我可以将userID作为整数发送,但是该示例旨在说明使用两个调用参数进行的操作
    • 由于上面的原始问题只有一个调用参数(即int id),因此这种情况甚至更简单