release/1.0.8-rc1 #42
2 changed files with 53 additions and 9 deletions
commit
46a9a84fbc
|
|
@ -88,7 +88,7 @@ public sealed class CircleMembersApiTests : IClassFixture<BlogsWebServerFixture>
|
||||||
}
|
}
|
||||||
|
|
||||||
private string MembersUrl(long circleId)
|
private string MembersUrl(long circleId)
|
||||||
=> $"{_fixture.Addresses.First(a => a.StartsWith("https://"))}/api/circle/{circleId}/members";
|
=> $"{_fixture.Addresses.First(a => a.StartsWith("https://"))}/{Constants.APIPrefix}/circle/{circleId}/members";
|
||||||
|
|
||||||
private HttpClient NewClient(string subject)
|
private HttpClient NewClient(string subject)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -57,12 +57,25 @@ namespace Yavsc.Blogs.Controllers
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Replaces a circle. The caller must own it; the server
|
/// Replaces a circle. The caller must own it; the server
|
||||||
/// reasserts ownership regardless of any OwnerId the client
|
/// reasserts ownership regardless of any <c>OwnerId</c>
|
||||||
/// tries to put in the body.
|
/// the client tries to put in the body.
|
||||||
|
///
|
||||||
|
/// <para>The body shape is a <see cref="CircleDto"/> — a
|
||||||
|
/// flat, navigation-free projection — not the EF entity.
|
||||||
|
/// The EF entity carries <c>[JsonIgnore]</c>-decorated
|
||||||
|
/// navigation properties (<c>Owner</c>, <c>Members</c>)
|
||||||
|
/// that bind to server-only types (<c>ApplicationUser</c>,
|
||||||
|
/// <c>CircleMember</c>); keeping the wire shape as a
|
||||||
|
/// DTO avoids any future regression where the entity
|
||||||
|
/// grows a navigable property that System.Text.Json
|
||||||
|
/// refuses to materialise. The client-side mirror lives
|
||||||
|
/// in <c>Yavsc.Api.Client.Dtos.CircleDto</c>.</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
// PUT: api/circle/5
|
// PUT: api/circle/5
|
||||||
[HttpPut("{id}")]
|
[HttpPut("{id}")]
|
||||||
public async Task<IActionResult> PutCircle([FromRoute] long id, [FromBody] Circle circle)
|
public async Task<IActionResult> PutCircle(
|
||||||
|
[FromRoute] long id,
|
||||||
|
[FromBody] CircleDto circle)
|
||||||
{
|
{
|
||||||
if (!ModelState.IsValid)
|
if (!ModelState.IsValid)
|
||||||
{
|
{
|
||||||
|
|
@ -82,9 +95,14 @@ namespace Yavsc.Blogs.Controllers
|
||||||
return new ChallengeResult();
|
return new ChallengeResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Force OwnerId to the caller; the body value is ignored.
|
// Map the wire shape onto the entity. OwnerId is
|
||||||
circle.OwnerId = uid;
|
// forced to the caller regardless of what the body
|
||||||
_context.Entry(circle).State = EntityState.Modified;
|
// says; Name and Public come from the body.
|
||||||
|
existing.Name = circle.Name;
|
||||||
|
existing.Public = circle.Public;
|
||||||
|
existing.OwnerId = uid;
|
||||||
|
|
||||||
|
_context.Entry(existing).State = EntityState.Modified;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -111,7 +129,7 @@ namespace Yavsc.Blogs.Controllers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
// POST: api/circle
|
// POST: api/circle
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<IActionResult> PostCircle([FromBody] Circle circle)
|
public async Task<IActionResult> PostCircle([FromBody] CircleDto circle)
|
||||||
{
|
{
|
||||||
if (!ModelState.IsValid)
|
if (!ModelState.IsValid)
|
||||||
{
|
{
|
||||||
|
|
@ -120,8 +138,14 @@ namespace Yavsc.Blogs.Controllers
|
||||||
|
|
||||||
var uid = User.GetUserId();
|
var uid = User.GetUserId();
|
||||||
circle.OwnerId = uid;
|
circle.OwnerId = uid;
|
||||||
|
Circle newCircle = new Circle
|
||||||
|
{
|
||||||
|
OwnerId = User.GetUserId(),
|
||||||
|
Name = circle.Name,
|
||||||
|
Public = circle.Public
|
||||||
|
};
|
||||||
|
|
||||||
_context.Circle.Add(circle);
|
_context.Circle.Add(newCircle);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _context.SaveChangesAsync(User.GetUserId());
|
await _context.SaveChangesAsync(User.GetUserId());
|
||||||
|
|
@ -322,6 +346,26 @@ namespace Yavsc.Blogs.Controllers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Wire shape for <c>PUT /api/circle/{id}</c>. Flat by
|
||||||
|
/// design — navigation properties (<c>Owner</c>,
|
||||||
|
/// <c>Members</c>) live on the EF entity only and never
|
||||||
|
/// cross the wire.
|
||||||
|
///
|
||||||
|
/// <para>Field names match the JSON the server emits
|
||||||
|
/// (camelCase via ASP.NET Core's Web defaults), so no
|
||||||
|
/// <c>[JsonPropertyName]</c> attributes are required.
|
||||||
|
/// Mirrors the client-side <c>Yavsc.Api.Client.Dtos.CircleDto</c>
|
||||||
|
/// — keep them in sync.</para>
|
||||||
|
/// </summary>
|
||||||
|
public sealed class CircleDto
|
||||||
|
{
|
||||||
|
public long Id { get; set; }
|
||||||
|
public string Name { get; set; } = string.Empty;
|
||||||
|
public string OwnerId { get; set; } = string.Empty;
|
||||||
|
public bool Public { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Wire shape for <c>GET /api/circle/{id}/members</c>.
|
/// Wire shape for <c>GET /api/circle/{id}/members</c>.
|
||||||
/// Mirrors <see cref="UserSearchResultDto"/> but stops
|
/// Mirrors <see cref="UserSearchResultDto"/> but stops
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue