【发布时间】: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