【问题标题】:ASP.NET Core Web API relational data - Error 504ASP.NET Core Web API 关系数据 - 错误 504
【发布时间】:2020-10-05 07:54:42
【问题描述】:

我一直在尝试在 .NET Core 中开发我的第一个 Web API 项目。我目前在检索关系数据时遇到问题。我正在使用存储库模型。

目前,我的存储库类中有以下内容:

    public IEnumerable<Children> GetAll()
    {
        return _context.Children;
    }

    public IEnumerable<Children> GetAll(int parentId)
    {
        return _context.Children.Where(c => c.ParentId == parentId).Include(c=>c.Parent);
    }

当我尝试在 Fiddler 中调用 GetAll() 函数时,它工作正常。但是当我尝试 GetAll(int parentId) 函数时,我得到一个 504 错误。

我在 Visual Studio 中设置了断点来测试第二种方法返回的数据,它返回的数据正常。

调用这个函数的Controller方法是:

    [Route("[action]")]
    [HttpGet]
    [Produces(typeof(DbSet<Children>))]
    public IActionResult GetChildrenOfCurrentLoggedInUser()
    {
        if (LoggedInUser.Id == null)
        {
            return null;
        }

        if (LoggedInUser.ParentId == 0)
        {
            var parent = _parentRepository.Find(LoggedInUser.Id);
            LoggedInUser.ParentId = parent.Result.Id;
        }

        var results = new ObjectResult(_childRepository.GetAll(LoggedInUser.ParentId))
        {
            StatusCode = (int)HttpStatusCode.OK
        };

        Request.HttpContext.Response.Headers.Add("X-Total-Count", _childRepository.GetAll(LoggedInUser.ParentId).Count().ToString());

        return results;
    }

这一切似乎都在检查,直到它给我错误。

编辑:

我已经进行了一些挖掘,并意识到我也遇到了与 POST 类似的问题。 POST 中的代码运行良好,但响应给了我错误。

以下代码的工作原理是正确保存数据,但不提供有效响应。

    [HttpPost]
    [Produces(typeof(Children))]
    public async Task<IActionResult> PostChildren([FromBody]ChildMinimalDTO child)
    {
        if (LoggedInUser.Id == null)
        {
            return BadRequest(ModelState);
        }

        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        var parent = _parentRepository.Find(LoggedInUser.Id);

        // Get the parentID from the current logged in user
        if (LoggedInUser.ParentId == 0)
        {
            LoggedInUser.ParentId = parent.Result.Id;
        }

        DateTime dateOfBirth = new DateTime(child.YearOfBirth, child.MonthOfBirth, child.DayOfBirth);
        Children newChild = new Children()
        {
            ChildName = child.ChildName,
            Dob = dateOfBirth,
            IsMale = child.IsMale,
            ParentId = LoggedInUser.ParentId,
        };

        await _childRepository.Add(newChild);

        return CreatedAtAction("PostChildren", new { id = newChild.Id }, newChild);
    }

但是,如果我做了一个小改动,它会提供有效的响应。

    [HttpPost]
    [Produces(typeof(Children))]
    public async Task<IActionResult> PostChildren([FromBody]ChildMinimalDTO child)
    {
        if (LoggedInUser.Id == null)
        {
            return BadRequest(ModelState);
        }

        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        var parent = _parentRepository.Find(LoggedInUser.Id);

        // Get the parentID from the current logged in user
        if (LoggedInUser.ParentId == 0)
        {
            LoggedInUser.ParentId = parent.Result.Id;
        }

        DateTime dateOfBirth = new DateTime(child.YearOfBirth, child.MonthOfBirth, child.DayOfBirth);
        Children newChild = new Children()
        {
            ChildName = child.ChildName,
            Dob = dateOfBirth,
            IsMale = child.IsMale,
            ParentId = LoggedInUser.ParentId,
        };

        await _childRepository.Add(newChild);

        newChild.Parent = null;

        return CreatedAtAction("PostChildren", new { id = newChild.Id }, newChild);
    }

唯一的变化是鬃毛 newChild.Parent 为空。将关系数据添加到响应中时,它的正确响应似乎确实存在问题。对于较早的问题,如果我从第二个函数中删除 .include,它会起作用。

这些是我正在使用的模型:

public class ChildMinimalDTO
{
    public string ChildName;
    public int DayOfBirth;
    public int MonthOfBirth;
    public int YearOfBirth;
    public bool IsMale;
    public int ParentId;
}

public partial class Children
{
    public Children()
    {
        Diaries = new HashSet<Diaries>();
    }

    public long Id { get; set; }
    public string ChildName { get; set; }
    public DateTime Dob { get; set; }
    public bool IsMale { get; set; }
    public int ParentId { get; set; }

    public Parents Parent { get; set; }
    public ICollection<Diaries> Diaries { get; set; }
}

public partial class Parents
{
    public Parents()
    {
        Children = new HashSet<Children>();
        SecurityQuestionParents = new HashSet<SecurityQuestionParents>();
    }

    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Address { get; set; }
    public string Address2 { get; set; }
    public string Town { get; set; }
    public string PostCode { get; set; }
    public int CountryId { get; set; }
    public string AspNetUserId { get; set; }

    public Countries Country { get; set; }
    public ICollection<Children> Children { get; set; }
    public ICollection<SecurityQuestionParents> SecurityQuestionParents { get; set; }
}

这就是我在创业课上的内容:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddScoped<ICountryRepository, CountryRepository>();
        services.AddScoped<IParentRepository, ParentRepository>();
        services.AddScoped<IChildRepository, ChildRepository>();
        services.AddScoped<IDiaryEntryRepository, DiaryEntryRepository>();
        services.AddScoped<IDiaryRepository, DiaryRepository>();
        services.AddScoped<IImageRepository, ImageRepository>();

        services.Configure<CookiePolicyOptions>(options =>
        {
            // This lambda determines whether user consent for non-essential cookies is needed for a given request.
            options.CheckConsentNeeded = context => true;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });

        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection")));

        services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddDefaultUI()
            .AddDefaultTokenProviders()
            .AddEntityFrameworkStores<ApplicationDbContext>();

        services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer("Data Source=184.168.194.60;Initial Catalog=Child_One;User ID=TickledPink;Password=ans10tech!;"));

        services.AddMvc().AddJsonOptions(options =>
        {
            options.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.DefaultContractResolver();
        });

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
            .AddRazorPagesOptions(options =>
            {
                options.AllowAreas = true;
                options.Conventions.AuthorizeAreaFolder("Identity", "/Account/Manage");
                options.Conventions.AuthorizeAreaPage("Identity", "/Account/Logout");
            });

        services.ConfigureApplicationCookie(options =>
        {
            options.LoginPath = $"/Identity/Account/Login";
            options.LogoutPath = $"/Identity/Account/Logout";
            options.AccessDeniedPath = $"/Identity/Account/AccessDenied";
        });

        services.AddHttpContextAccessor();
        services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
        services.AddSingleton<IEmailSender, EmailSender>();

        services.AddTransient<IPrincipal>(provider => provider.GetService<IHttpContextAccessor>().HttpContext.User);
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider serviceProvider)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseCookiePolicy();

        app.UseAuthentication();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });

        // For Unity WebGL integration
        app.UseFileServer();
        StaticFileOptions staticFileOptions = new StaticFileOptions()
        {
            FileProvider = new PhysicalFileProvider(
                Path.Combine(Directory.GetCurrentDirectory(), @"Template")),
            RequestPath = new PathString("/template")
        };
        app.UseStaticFiles(staticFileOptions);
        FileExtensionContentTypeProvider contentTypeProvider = (FileExtensionContentTypeProvider)staticFileOptions.ContentTypeProvider ??
            new FileExtensionContentTypeProvider();
        contentTypeProvider.Mappings.Add(".unityweb", "application/octet-stream");
        staticFileOptions.ContentTypeProvider = contentTypeProvider;
        app.UseStaticFiles(staticFileOptions);

        //CreateRoles(serviceProvider);
    }

【问题讨论】:

  • 尝试返回简单值,然后区分两个结果
  • 我做了更多的挖掘,发现每当我尝试返回一个附加了关系数据的对象时,这都是一个问题。我已经修改了帖子以提供更多信息。

标签: asp.net api web asp.net-core-webapi


【解决方案1】:

解决了。由于父模型和子模型之间的链接,错误似乎归结为它正在检索循环结果。

这篇文章给了我答案。

Asp.Net Core Web API 2.2 Controller not returning complete JSON

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-10
    • 2017-02-03
    • 2017-05-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多