简体   繁体   English

ASP.NET 核心 Web API 关系数据 - 错误 504

[英]ASP.NET Core Web API relational data - Error 504

I've been trying to develop my first Web API project in .NET Core.我一直在尝试在 .NET Core 中开发我的第一个 Web API 项目。 I'm currently experiencing an issue when I retrieve relational data.我目前在检索关系数据时遇到问题。 I'm using the repository model.我正在使用存储库 model。

At the moment, I have the following in my repository class:目前,我的存储库 class 中有以下内容:

    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);
    }

When I try calling the GetAll() function in Fiddler, it works fine.当我尝试在 Fiddler 中调用 GetAll() function 时,它工作正常。 But when I try the GetAll(int parentId) function, I get a 504 Error.但是当我尝试 GetAll(int parentId) function 时,出现 504 错误。

I've set breakpoints in visual studio to test the data being returned by the second method and it returns the data okay.我在visual studio中设置了断点来测试第二种方法返回的数据,它返回的数据没问题。

The Controller method that calls this function is:调用此 function 的 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;
    }

It all seems to check out until it gives me the error.这一切似乎都在检查,直到它给我错误。

Edit:编辑:

I've done some digging and realised I'm getting similar issues with the POST as well.我已经进行了一些挖掘,并意识到我也遇到了与 POST 类似的问题。 The code within the POST works perfectly but the response is giving me errors. POST 中的代码运行良好,但响应给了我错误。

The following code works in that it saves the data correctly but it doesn't provide a valid response.以下代码的工作原理是它正确保存了数据,但它没有提供有效的响应。

    [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);
    }

But, if I make a minor change, it provides a valid response.但是,如果我做一个小改动,它会提供一个有效的响应。

    [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);
    }

The only change was to mane newChild.Parent null.唯一的变化是鬃毛 newChild.Parent null。 There does seem to be a problem with it responding correctly when the relational data is added to the response.将关系数据添加到响应中时,它的正确响应似乎确实存在问题。 With the earlier issue, if I remove the.include from the second function, it works.对于较早的问题,如果我从第二个 function 中删除 .include,它可以工作。

These are the models I'm working with:这些是我正在使用的模型:

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; }
}

And this is what I have in my startup class:这就是我在我的启动 class 中所拥有的:

    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);
    }

Solved it.解决了。 The error appeared to be down to the fact that it was retrieving cyclic results because of the link between the Parent and Children models.由于父模型和子模型之间的链接,错误似乎归结为它正在检索循环结果。

This post gave me the answer.这篇文章给了我答案。

Asp.Net Core Web API 2.2 Controller not returning complete JSON Asp.Net Core Web API 2.2 Controller 未返回完整 Z0ECD11C1D7A3BB87401D8D148A2

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM