Skip to content

Commit 1fa4605

Browse files
committed
Can_Update_Many_To_Many test (failing)
1 parent 542b021 commit 1fa4605

File tree

4 files changed

+69
-0
lines changed

4 files changed

+69
-0
lines changed

src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,11 +212,14 @@ private void AttachHasManyThrough(TEntity entity, HasManyThroughAttribute hasMan
212212
// or we might be able to create a proxy type and implement the enumerator
213213
var throughRelationshipCollection = Activator.CreateInstance(hasManyThrough.ThroughProperty.PropertyType) as IList;
214214
hasManyThrough.ThroughProperty.SetValue(entity, throughRelationshipCollection);
215+
215216
foreach (var pointer in pointers)
216217
{
217218
_context.Entry(pointer).State = EntityState.Unchanged;
218219

219220
var throughInstance = Activator.CreateInstance(hasManyThrough.ThroughType);
221+
_context.Entry(throughInstance).State = EntityState.Added;
222+
220223
hasManyThrough.LeftProperty.SetValue(throughInstance, entity);
221224
hasManyThrough.RightProperty.SetValue(throughInstance, pointer);
222225
throughRelationshipCollection.Add(throughInstance);
@@ -249,6 +252,8 @@ public virtual async Task<TEntity> UpdateAsync(TId id, TEntity entity)
249252
foreach (var relationship in _jsonApiContext.RelationshipsToUpdate)
250253
relationship.Key.SetValue(oldEntity, relationship.Value);
251254

255+
AttachRelationships(entity);
256+
252257
await _context.SaveChangesAsync();
253258

254259
return oldEntity;

src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,10 @@ private object SetHasManyRelationship(object entity,
283283

284284
if (relationships.TryGetValue(relationshipName, out RelationshipData relationshipData))
285285
{
286+
if(relationshipData.IsHasMany == false) {
287+
throw new JsonApiException(400, $"Cannot set HasMany relationship '{attr.PublicRelationshipName}'. Value must be a JSON array of Resource Identifier Objects.");
288+
}
289+
286290
var data = (List<ResourceIdentifierObject>)relationshipData.ExposedData;
287291

288292
if (data == null) return entity;

test/JsonApiDotNetCoreExampleTests/Acceptance/ManyToManyTests.cs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,5 +122,59 @@ public async Task Can_Create_Many_To_Many()
122122
var persistedArticleTag = Assert.Single(persistedArticle.ArticleTags);
123123
Assert.Equal(tag.Id, persistedArticleTag.TagId);
124124
}
125+
126+
[Fact]
127+
public async Task Can_Update_Many_To_Many()
128+
{
129+
// arrange
130+
var context = _fixture.GetService<AppDbContext>();
131+
var tag = _tagFaker.Generate();
132+
var article = _articleFaker.Generate();
133+
context.Tags.Add(tag);
134+
context.Articles.Add(article);
135+
await context.SaveChangesAsync();
136+
137+
var route = $"/api/v1/articles/{article.Id}";
138+
var request = new HttpRequestMessage(new HttpMethod("PATCH"), route);
139+
var content = new
140+
{
141+
data = new
142+
{
143+
type = "articles",
144+
id = article.StringId,
145+
relationships = new Dictionary<string, dynamic>
146+
{
147+
{ "tags", new {
148+
data = new [] { new
149+
{
150+
type = "tags",
151+
id = tag.StringId
152+
} }
153+
} }
154+
}
155+
}
156+
};
157+
158+
request.Content = new StringContent(JsonConvert.SerializeObject(content));
159+
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.api+json");
160+
161+
// act
162+
var response = await _fixture.Client.SendAsync(request);
163+
164+
// assert
165+
var body = await response.Content.ReadAsStringAsync();
166+
Assert.True(HttpStatusCode.OK == response.StatusCode, $"{route} returned {response.StatusCode} status code with payload: {body}");
167+
168+
var articleResponse = _fixture.GetService<IJsonApiDeSerializer>().Deserialize<Article>(body);
169+
Assert.NotNull(articleResponse);
170+
171+
_fixture.ReloadDbContext();
172+
var persistedArticle = await _fixture.Context.Articles
173+
.Include(a => a.ArticleTags)
174+
.SingleAsync(a => a.Id == articleResponse.Id);
175+
176+
var persistedArticleTag = Assert.Single(persistedArticle.ArticleTags);
177+
Assert.Equal(tag.Id, persistedArticleTag.TagId);
178+
}
125179
}
126180
}

test/JsonApiDotNetCoreExampleTests/Acceptance/TestFixture.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using Microsoft.AspNetCore.TestHost;
77
using JsonApiDotNetCore.Services;
88
using JsonApiDotNetCore.Data;
9+
using Microsoft.EntityFrameworkCore;
910

1011
namespace JsonApiDotNetCoreExampleTests.Acceptance
1112
{
@@ -33,6 +34,11 @@ public TestFixture()
3334
public IJsonApiDeSerializer DeSerializer { get; private set; }
3435
public IJsonApiContext JsonApiContext { get; private set; }
3536
public T GetService<T>() => (T)_services.GetService(typeof(T));
37+
38+
public void ReloadDbContext()
39+
{
40+
Context = new AppDbContext(GetService<DbContextOptions<AppDbContext>>());
41+
}
3642

3743
private bool disposedValue = false;
3844
protected virtual void Dispose(bool disposing)

0 commit comments

Comments
 (0)